Entwickler-Ecke
WinForms - OpenFileDialog in einem neuen Thread öffnen
xToast - Fr 08.10.10 13:43
Titel: OpenFileDialog in einem neuen Thread öffnen
Ich möchste einen openFileDialog in einem neuen Thread öffnen, allerdings bekomm ich dabei immer eine Fehlermeldung:
"Für den aktuellen Thread muss der STA-Modus (Single Thread Apartment) festgelegt werden, bevor OLE-Aufrufe ausgeführt werden können. Stellen Sie sicher, dass die Hauptfunktion mit STAThreadAttribute gekennzeichnet ist. Diese Ausnahme wird nur ausgelöst, wenn ein Debugger mit dem Prozess verbunden ist."
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:
| private void mapToolStripMenuItem1_Click(object sender, EventArgs e) { Thread loadMapThread = new Thread(new ThreadStart(loadMap)); loadMapThread.Start();
loadMapThread.Interrupt(); }
private void loadMap() { OpenFileDialog openMapDialog = new OpenFileDialog();
openMapDialog.AddExtension = true; openMapDialog.CheckFileExists = false; openMapDialog.CheckPathExists = false; openMapDialog.Filter = "Maps (*.png)|*.png; *.PNG"; openMapDialog.Multiselect = false; openMapDialog.ValidateNames = false; openMapDialog.Title = "Map öffnen";
if (openMapDialog.ShowDialog() == DialogResult.OK) { try { Thread.Sleep(1000); } catch { Thread.Sleep(1000);
return; } } else { Thread.Sleep(1000);
return; } } |
Das [STAThread] hab ich schon in meiner main Methode. Wo und was muss ich einfügen damit der OFD ohne Fehlermeldung geöffnet wird?
Th69 - Fr 08.10.10 13:57
Alle WinForms-Elemente (auch Dialoge) müssen im GUI-Mainthread ausgeführt werden. Du könntest aber mittels "Control.Invoke" (bzw. Form.Invoke) den Dialog vom Thread aus anzeigen lassen.
Bei deinem Beispielcode reicht es aber doch, wenn du erst den OpenFileDialog aufrufst und danach dann den Thread (mit dem ausgewählten Dateinamen als Parameter) startest!
Aber was das Thread.Sleep() dort jeweils soll verstehe ich nicht...
xToast - Fr 08.10.10 14:30
Zitat: |
Bei deinem Beispielcode reicht es aber doch, wenn du erst den OpenFileDialog aufrufst und danach dann den Thread (mit dem ausgewählten Dateinamen als Parameter) startest! |
Nein, das reicht in meinem fall nicht. Ich hab nämlich ein Control, was sich nach dem öffnen des Dialogs nicht wieder weiterrendert (XNA), dann dacht ich mir, wieso den Dialog nich in nem neuen Thread starten? Naja, danke für deinen Tipp, ich schaus mir mal an.
Zitat: |
Aber was das Thread.Sleep() dort jeweils soll verstehe ich nicht... |
Ich muss den Thread ja erstamal in einen bestimmten Zustand (hab grad den Namen vergessen) versetzen, damit ich ihn dann mit Interrupt() "löschen" kann.
Kha - Fr 08.10.10 15:12
xToast hat folgendes geschrieben : |
Nein, das reicht in meinem fall nicht. Ich hab nämlich ein Control, was sich nach dem öffnen des Dialogs nicht wieder weiterrendert (XNA), dann dacht ich mir, wieso den Dialog nich in nem neuen Thread starten? |
Ich weiß nicht, ob irgendwo noch versteckte Fallgruben lauern, aber in diesem Fall könnte ein neuer Thread wirklich sinnvoll sein. Schau mal, ob du in der Thread-Klasse etwas zu STA findest ;) .
xToast hat folgendes geschrieben : |
Zitat: | Aber was das Thread.Sleep() dort jeweils soll verstehe ich nicht... |
Ich muss den Thread ja erstamal in einen bestimmten Zustand (hab grad den Namen vergessen) versetzen, damit ich ihn dann mit Interrupt() "löschen" kann. |
Huch? Threads werden am Ende der Methode automatisch entfernt, was genau hast du mit dem Interrupt vor?
xToast - Fr 08.10.10 17:31
Zitat: |
Huch? Threads werden am Ende der Methode automatisch entfernt, was genau hast du mit dem Interrupt vor? |
Achso, das wusste ich nicht, werd ich dann macl schnell ausbessern :D
Zitat: |
Ich weiß nicht, ob irgendwo noch versteckte Fallgruben lauern, aber in diesem Fall könnte ein neuer Thread wirklich sinnvoll sein. Schau mal, ob du in der Thread-Klasse etwas zu STA findest ;) . |
In der MSDN hab ich leider nichts weiterhelfendes gefunden, deshalbt frag ich hier nach^^
Kha - Fr 08.10.10 17:46
Dann schau ich eben nach... :P
C#-Quelltext
1:
| Thread.SetApartmentState |
xToast - Fr 08.10.10 19:16
Danke, das klappt jetzt soweit :D
Aber kann es sein, das man aus einem Thread nicht auf die Variablen in einem anderen Tread zugreifen kann?
Kha - Fr 08.10.10 19:34
Generell schon, aber damit wären wir beim großen Thema Thread-Synchronisierung, das den Rahmen dieses Threads sprengen dürfte ;) . Am einfachsten machst du es dir, wenn du dem Thread am Anfang schon alle Informationen übergeben kannst, auf die er keinen Schreibzugriff braucht.
xToast - Fr 08.10.10 20:37
Huh, naja, ich habe genau 2 Variablen die von diesem Thread geändert werden müssen.
1 bool-Varible
und 1 String.
Kennst du vielleicht einen Link, wo das synchronisieren vonn 2 Variablen erläutert wird?
Ich höhre den Begriff im Rahmen der Programmierung zum ersten mal und weiß nicht, wonach ich genau google muss^^
Yogu - Fr 08.10.10 22:52
Am einfachsten ist es, eine Klasse zu erstellen, die genau diese Objekte beinhaltet. Auf Instanzen dieser Klasse kann aus allen Threads lesend und schreibend zugegriffen werden.
Edit: Macht natürlich keinen Unterschied, ob auf Felder in der Formularklasse oder einer anderen Instanz zugegriffen wird. Ich hab zu schlampig gelesen :oops:
Kha - Fr 08.10.10 23:40
Yogu hat folgendes geschrieben : |
Auf Instanzen dieser Klasse kann aus allen Threads lesend und schreibend zugegriffen werden. |
Solltest du auf Race Conditions aus sein, die schaffst du auch mit Klassenfeldern der Form-Klasse ;P .
Für euch beide vielleicht mal das komplette Programm :) :
http://www.yoda.arachsys.com/csharp/threads/
Yogu - Sa 09.10.10 00:44
Ok, je nach Implementierung kann das zu Problem führen. Die
Monitor [
http://msdn.microsoft.com/de-de/library/system.threading.monitor.aspx]-Klasse kannte ich vorher noch nicht; sie sieht ganz nett aus. Danke! :)
xToast hat folgendes geschrieben : |
Huh, naja, ich habe genau 2 Variablen die von diesem Thread geändert werden müssen.
1 bool-Varible
und 1 String. |
Also der Wert, der angibt, ob das Dialogfenster mit OK bestätigt wurde, und der Dateiname?
Dann würde ich nicht in Felder schreiben, sondern Methoden per
Invoke aufrufen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| if (openMapDialog.ShowDialog == DialogResult.OK) { loadMap(openMapDialog.FileName); Invoke(new Action(showMap)); }
void loadMap(string fileName) { }
void showMap() { } |
Invoke stellt sicher, dass nur aus dem Hauptthread auf Formularelemente zugegriffen wird.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!