Schon wieder was zu WPF

Hallo zusammen,

ich hab schon wieder das nächste Problem mit WPF:
und zwar möchte ich bei einem Hintergrundprozess, der eine ganze Weile dauern kann, ein Statusfenster anzeigen lassen, damit man sehen kann, wie weit das Programm denn schon ist.

Konkret geht es darum, die gesamte Festplattenhierarchie (also alle Ordner, Unterordner, Dateien) einzulesen und in einer sinnvollen Datenstruktur zu speichern. Dies ist also nur ein einziges Mal nach Programminstallation nötig.

Während des Vorganges soll man schonmal einige Sachen angezeigt bekommen, wie z.B Gesamtgröße aller bisher gefundenen Dateien, Ordner etc.

Dafür rufe ich einen Thread auf, der diesen Vorgang initialisiert und auch das Statusfenster erzeugen soll.

private static void InitializeJob(object Data)
{
Classname newClass = new Classname();

Das 2. Fenster besitzt natürlich seine eigene Klasse, die ich zunächst erzeugen muss. Doch wenn ich das tun will, kommt nur die Fehlermeldung
„Beim aufrufenden Thread muss es sich um einen STA-Thread handeln, da dies für viele Komponenten der Benutzeroberfläche erforderlich ist.“

Ich habe auch schon in allen möglichen Foren nachgesehen, aber meiner Meinung nach ergibt die Meldung gar keinen Sinn. Schließlich hab ich ja noch gar nicht auf irgendwelche Sachen in dem Fenster zugegriffen, sondern nur dessen Klasse erstellt…

Was mache ich also falsch?

Bin für jede Antwort dankbar.

Bluesky787

Hallo!
Lies mal hier nach:
http://stackoverflow.com/questions/1293402/why-does-…

Und bitte benenn’ Deine Klassen sinnvoll.
Du hast einen ordentlichen Namen, also verdienen Deine Klassen auch einen.
Oder heißt Du „Kind1“?

Gruß,
Martin

Hallo,

eine Klasse, die eine Fensterklasse kapselt, klingt erst mal schon verdächtig. Üblicherweise werden Fenster erstellt, indem die Window-Klasse o.Ä. abgeleitet wird und diese Klasse kann direkt instanziert werden. Keine Ahnung, warum man da noch eine weitere Klasse drumrum bauen sollte.
Das Problem bei dir ist, dass du ein GUI-Element aus einem Nicht-GUI-Thread erzeugen willst (was vermutlich in dem Konstruktor passiert). Und das darf nicht sein. Du kannst den Aufruf mit dem Dispatcher auf den GUI-Thread verlagern:

Dispatcher.Invoke((Action)() =\> {
 //neues Objekt erstellen...
 //andere GUI-Sachen machen.
});

Noch ein paar allgemeine Hinweise:
Neue Threads zu erzeugen ist schon seit einiger Zeit nicht mehr elegant (es sei denn, es geht wirklich nicht anders). Einerseits kostet das Erzeugen von Threads etwas Zeit und andererseits gibt es im .Net-Framework Klassen, die schon optimiert sind. Z.B. könntest du ThreadPool.QueueUserWorkItem() verwenden, um schon vorhandene Threads zu nutzen. Mit Task.Run() bzw. Task.Factory.StartNew() musst du dir darum gar keine Gedanken machen, da die Funktionen die momentan optimale Lösung nutzen.
Um den Zwischenstand anzuzeigen bietet sich DataBinding zu einem ViewModel an. Dann müsstest du nur die Properties ändern und nicht auf GUI-Elemente zugreifen. Das Problem mit dem GUI-Thread bleibt dann allerdings trotzdem. Hier könntest du bspw. das Feuern des PropertyChanged-Events in den GUI-Thread schieben.

Nico

Hallo nochmal,
die Benennung der Klassen war selbstverständlich nur beispielhaft und im Programm haben sie einen sinnvollen Namen…
Ich danke für die Antworten und möchte dabei allen, die das selbe Problem haben, folgenden Link mitgeben, der mir schlussendlich jedoch am weitesten aus der Misere geholfen hat, weil er exakt das Problem behandelt, dass ich hatte (schließlich doch noch gefunden):

http://elegantcode.com/2009/07/03/wpf-multithreading…

Viele Grüße,
Bluesky787