Autor Beitrag
xToast
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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."

ausblenden volle Höhe 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:
        //Thread starten
        private void mapToolStripMenuItem1_Click(object sender, EventArgs e) //beim Klick soll der Thread gestartet werden
        {
            Thread loadMapThread = new Thread(new ThreadStart(loadMap));
            loadMapThread.Start();

            //Thread schließen
            loadMapThread.Interrupt();
        }

        //Map öffnen
        private void loadMap()
        {
            //openFileDialog
            OpenFileDialog openMapDialog = new OpenFileDialog();

            //openFileDialog Filter setzen
            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 unterbrechen
                    Thread.Sleep(1000);
                }
                catch
                {
                    //...

                    //Thread unterbrechen
                    Thread.Sleep(1000);

                    return;
                }
            }
            else
            {
                //...

                //Thread unterbrechen
                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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4795
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 08.10.10 15:12 
user profile iconxToast hat folgendes geschrieben Zum zitierten Posting springen:
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 ;) .

user profile iconxToast hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 08.10.10 17:46 
Dann schau ich eben nach... :P
ausblenden C#-Quelltext
1:
Thread.SetApartmentState					

_________________
>λ=

Für diesen Beitrag haben gedankt: xToast
xToast Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: 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:


Zuletzt bearbeitet von Yogu am Sa 09.10.10 00:46, insgesamt 2-mal bearbeitet
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 08.10.10 23:40 
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: 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! :)

user profile iconxToast hat folgendes geschrieben Zum zitierten Posting springen:
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:

ausblenden 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.