PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : VB.NET-Threads und Steuerelemente


Gast
2010-01-01, 18:09:54
Frohes neues Jahr

da mein Programm einen sehr zeitaufwändigen Vorgang durchführt, habe ich diesen in einen Thread a la thread.start gelegt, damit die Oberfläche weiterhin reagiert. Um den Status der Bearbeitung auf der Oberfläche darzustellen, möchte ich den Text eines Labels ändern. Die benötigte Information dazu kommt aus der Klasse die diese Operation durchführt und den Wert je nach Bearbeitungsstatus ändert (bei mir das jeweils letzte bearbeitete File) Nur irgendwie bekomme ich das nicht hin.
Hab schon etwas geguckt und den Backgroundworker gefunden, aber ich bin mir nicht sicher, ob das wirklich das ist, das dafür geeignet ist, insbesondere wenn ich später weitere Threads hinzufüge die neben diesem laufen bzw. dachte ich dieser sei nicht für Benutzerinteraktionen geeignet. Ich habe irgendwo in der msdn gelesen, man soll in einem Thread nicht auf die Steuerelemente einer Form-Control zugreifen, da dies eine schäbige Vorgehensweise sein soll.
Meine Fragen:
1. Was ist ganz grob die bevorzugte Vorgehensweise um in/durch einen Thread Eigenschaften von Steuerelementen zu ändern.
2. Ich habe noch in Erinnerung, dass ggf. die ganze Form und nicht nur mein Label neu gezeichnet wird, wenn ich ein Steuerelement schnell aktualisere, stimmt das? Wie kann man das feststellen oder unterbinden, sonst fängt das an zu flackern, das Programm reagiert bereits mit meinem simplen Thread ziemlich träge.

Monger
2010-01-01, 19:33:13
1) Eine Windows Forms Applikation ist normalerweise Single-Threaded, und aus gutem Grund: früher hat man tatsächlich versucht, Controls threadsicher zu designen, und das hat sich bald als ganz schlechte Idee erwiesen. Deshalb sollten alle Änderungen an den Controls im selben Thread laufen.

Es gibt aber einige Möglichkeiten, quasi in einem nebenläufigen Thread irgendwelche Berechnungen zu machen, und die Controls im Haupthread zu manipulieren. Dazu hat jedes Control die Methoden Invoke, BeginInvoke, EndInvoke und InvokeLater (dazu hier mehr: http://msdn.microsoft.com/de-de/library/ms951089.aspx).
Da das aber oftmals ziemlich kompliziert ist, gibt es Klassen wie den Backgroundworker, der das intern übernimmt.

Wenn du kannst, benutz vorgefertige Konstrukte wie eben den Backgroundworker. Multithreading mit Windows Forms ist viel komplexer als es zu Anfang aussieht.

2) Eigentlich trennen die Controls ganz bewusst zwischen Rendering und innerer Zustandsänderung. Sprich: wenn du fünfmal hintereinander einen Button aktivierst und wieder deaktivierst, sollte da eigentlich nicht jedesmal und sofort zu einem neu zeichnen führen. Es sei denn natürlich, du erzwingst es über "invalidate", o.ä.
Schon deshalb solltest du es vermeiden, die Controls von Hand neu zu validieren.

Gast
2010-01-01, 23:02:44
Falls ein anderes Toolkit eine Alternative ist, sieh dir mal Qt an. Mit der QThread Klasse solltest du relativ einfach hinbekommen was du beschreibst.

Yavion
2010-01-05, 22:00:58
1.
Normalerweise macht man (zumindest ich) es so. Controls bzw deren Handler (z.B. aus einer Form) aktivieren Serviceklassen, die wiederum Threads starten, in denen irgendetwas getan wird und die Ergebnisse via form.invoke(delegate, object) wieder in die form schreiben.

Eigentlich sollte man sich nur merken, dass man aus einem anderen Thread ausschließlich über invoke auf ein Control (z.B. eine Form) zugreifen darf.
Das ist in sofern wichtig, weil man sonst die eigenartigsten Dinge erleben kann und wird.
Nun kannst Du mit invoke so ziemlich alles machen, da du beliebige funktionen und argumente übergeben darfst.
Allerdings muss man trotzdem aufpassen, denn gerade wenn man mit mehreren Fenstern arbeitet, kann es einem durchaus passieren, dass ein Fenster einfach mal weg ist. :rolleyes:

2. Hier macht MS einen guten Job. Wenn ein Control erstmal initialisiert wurde, gehen die Updates m.E. recht fix. Da würde ich mir über so Dinge wie flackern normalerweise keine Sorgen machen aber:
Wenn dein Programm träge *reagiert* ist es höchstwahrscheinlich noch nicht wirklich threaded.

Gast
2010-01-10, 03:17:03
Danke für die Antworten, haben mich um so einiges weiter gebracht. Verwende bis jetzt noch einen Backgroundworker als temporäre Lösung, aber wie ich mir schon dachte, ist das nicht das was ich eigentlich haben will. qt würde ich gerne machen, aber da bin ich leider noch auf einem hello world niveau. ist es aber sicher mal wert, sich eingehend damit zu beschäftigen.

Ich habe zwischenzeitlich im Netz noch hilfreiche FAQs zu diesen Themen gefunden, die mir ebenfalls weitergeholfen haben, falls mal jemand sowas sucht:
http://www.mycsharp.de/wbb2/board.php?boardid=70

Ist eben auch eine Erfahrungssache, habe noch nicht so viel mit Threads gemacht, nur mit Java ein bisschen. Gibt ja genügend Anleitungen, aber das mit den Windows Form Controls war mir überhaupt nicht klar. Vielen Dank

mfg