Autor |
Beitrag |
xToast
      
Beiträge: 27
|
Verfasst: Fr 08.10.10 13:43
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."
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
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: 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 
      
Beiträge: 27
|
Verfasst: 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
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 08.10.10 15:12
|
|
xToast 
      
Beiträge: 27
|
Verfasst: 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
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
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 08.10.10 17:46
Für diesen Beitrag haben gedankt: xToast
|
|
xToast 
      
Beiträge: 27
|
Verfasst: Fr 08.10.10 19:16
Danke, das klappt jetzt soweit
Aber kann es sein, das man aus einem Thread nicht auf die Variablen in einem anderen Tread zugreifen kann?
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: 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 
      
Beiträge: 27
|
Verfasst: 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
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: 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 
Zuletzt bearbeitet von Yogu am Sa 09.10.10 00:46, insgesamt 2-mal bearbeitet
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: 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  : www.yoda.arachsys.com/csharp/threads/
_________________ >λ=
Für diesen Beitrag haben gedankt: Yogu
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Sa 09.10.10 00:44
Ok, je nach Implementierung kann das zu Problem führen. Die Monitor-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.
|
|