Hallo,
Wenn ich aus einem Thread heraus, einen Dialog mit ShowModal aufrufe, bleibt das Programm hängen und stürzt ab. Das passiert mit allen Dialogen außer mit dem wxMessageDialog.
Den Thread starte ich mit => thread.start_new_thread(...)
Wie kann ich das Problem lösen?
ShowModal-Problem innerhalb eines Threads
Innerhalb eines threads auf gui elemente zugreifen bringt Probleme mit sich.HarryH hat geschrieben:Hallo,
Wenn ich aus einem Thread heraus, einen Dialog mit ShowModal aufrufe, bleibt das Programm hängen und stürzt ab. Das passiert mit allen Dialogen außer mit dem wxMessageDialog.
Den Thread starte ich mit => thread.start_new_thread(...)
Wie kann ich das Problem lösen?
Soweit ich mich erinnere, ist nur der wx.MessageDialog threadsafe.
Ich habe auch einmal dieses Problem gehabt, wobei mir in der wxPython-User list geraten wurde,
alle gui sachen im mainthread zu erledigen.
(Aus den worker threads mit wx.PostEvent an
den mainthread weiterposten).
Vielleicht auch hilfreich:
http://wiki.wxpython.org/index.cgi/LongRunningTasks
http://wiki.wxpython.org/index.cgi/WorkingWithThreads
Hallo Francesco,
Danke für deine Informationen.
Ich bin auch noch auf eine andere Lösung gekommen. Die Probleme treten nämlich nur auf, wenn ich mit ShowModal auf den Dialog zugreife, nicht bei Show. Allerdings sollte in meinem Fall die Anwendung warten.
Deswegen bin ich noch auf folgenden Lösung gekommen:
Diese Methode füge ich zu dem Dialog hinzu, und rufe ihn damit auf.
MIt dem Thread innerhalb der Methode wird der Dialog angezeigt.
Die erste Schleife wartet bis der Dialog IsShown() ist und bricht dann ab. Die zweite Schleife wartet bis der Dialog geschlossen ist.
Evtl. könnte mann noch einen Returncode am Ende der Funktion eingeben.
Allerdings muss der Dialog außerhalb des Threads erzeugt werden!
Danke für deine Informationen.
Ich bin auch noch auf eine andere Lösung gekommen. Die Probleme treten nämlich nur auf, wenn ich mit ShowModal auf den Dialog zugreife, nicht bei Show. Allerdings sollte in meinem Fall die Anwendung warten.
Deswegen bin ich noch auf folgenden Lösung gekommen:
Code: Alles auswählen
def MakeModal(self):
""" Makes the dialog modal inside a thread """
thread.start_new_thread(self.Show,())
while not self.IsShown():
time.sleep(0.01)
while self.IsShown():
time.sleep(0.1)
MIt dem Thread innerhalb der Methode wird der Dialog angezeigt.
Die erste Schleife wartet bis der Dialog IsShown() ist und bricht dann ab. Die zweite Schleife wartet bis der Dialog geschlossen ist.
Evtl. könnte mann noch einen Returncode am Ende der Funktion eingeben.
Allerdings muss der Dialog außerhalb des Threads erzeugt werden!
Gruß, Harry
Hallo Harry,HarryH hat geschrieben:Hallo Francesco,
Danke für deine Informationen.
Ich bin auch noch auf eine andere Lösung gekommen.
bitte, bin leider auch kein profi und versuche selbst, threads zu vermeiden.
Gute Idee Deine Lösung.
Wenn ich ein Event weiterposte und dann einen Dialog mit ShowModal aufrufe wird dann auch der Thread angehalten oder läuft er weiter?Francesco hat folgendes geschrieben:
Aus den worker threads mit wx.PostEvent an
den mainthread weiterposten
Und könnte mir jemand zeigen wie das mit dem wx.PostEvent funktioniert?
Gruß, Harry
HarryH hat geschrieben:Wenn ich ein Event weiterposte und dann einen Dialog mit ShowModal aufrufe wird dann auch der Thread angehalten oder läuft er weiter?Francesco hat folgendes geschrieben:
Aus den worker threads mit wx.PostEvent an
den mainthread weiterposten
Und könnte mir jemand zeigen wie das mit dem wx.PostEvent funktioniert?
Hallo, habe einen alten code gefunden.
So habe ich das damals in etwa gemacht:
g_thread_event = threading.Event()
thread:
Globals.g_strTitle = _("Overwrite %s ?") % strFile
Globals.g_thread_event.clear()
event = wxCommandEvent ()
event.SetEventType (wxEVT_COMMAND_BUTTON_CLICKED)
event.SetId (19999)
pFrm = wxGetApp().GetFrame()
if(pFrm):
wxPostEvent(pFrm, event)
Globals.g_thread_event.wait ()
return Globals.g_nGuiResult
main:
EVT_BUTTON(self, 19999, self.OnOverwriteDlg)
def OnOverwriteDlg(self, event):
dlg = COverwriteDlg (self)
dlg.m_wndInfoLabel.SetLabel (Globals.g_strTitle)
Globals.g_nGuiResult = dlg.ShowModal()
Globals.g_thread_event.set ()