Once more: threads and events Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Kraymer
Earned a small fee
Earned a small fee
Posts: 23
Joined: Wed Feb 04, 2009 1:32 pm
Location: Germany
Contact:

Once more: threads and events

Post by Kraymer » Wed May 20, 2009 9:36 am

Hello everyone!

I'm having a hard time using my custom events (actually it's only one atm) from threads. More specifically, the events are not received by the controlling class which starts the thread and is responsible for the program "to work". Latter class lies within a GUI.

I followed the "custom events" page's instruction in the wiki and also had some help on IRC (thanks, folks, and special thanks to DavidGH!) to flatten out some issues that might have been problematic too but in the end, my class still fails to respond to the event.

So I have this GUI class, which instantiates a "control" class which, in turn, starts and stops threads to do some work. What I want now is that given control class is informed when, e.g. an error occurs. My app fails there already :( The next step would be to pass that on to the GUI, but coming from the control then. The GUI has no knowledge about the control's workings and the threads.

All the samples I found regarding threading and events refer to wxFrame to get an event handler. Well, I want the control class to be independent of the GUI. While at the moment it's created in a wxFrame, I want it to be logically separated and e.g. be possible to use that class in a console application.
What I tried was calling AddPendingEvent(..) inside the thread's Entry() routine
  • * using the GetEvtHandler() from wxGetApp()
    * after inheriting the control class from wxEvtHandler and passing a control instance to the thread
    * after inheriting the control class from wxEvtHandler, "pushing" that EventHandler and passing a control instance to the thread
I also tried to just create a wxEventHandler instance inside the thread but of course, that didn't work either.


Posting the whole project code here would certainly be considered spam so I zipped a ripped down minimal sample from my project and attach it to this post. Maybe someone likes to look at it. Any help is highly appreciated. In case of enlightenment I'm offering to improve the wiki page or create a new one of my own :)

Thanks, guys.

Kraymer


PS: I'm using wxWidgets 2.8.9 with Visual Studio 2005 (for which a project solution is provided).
Attachments
threadevents_minmal_sample.zip
Sample code to show/reproduce the problem.
(9.62 KiB) Downloaded 56 times

User avatar
doublemax
Moderator
Moderator
Posts: 15182
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Wed May 20, 2009 11:10 am

main mistake, wrong order of "id, commandType":

Code: Select all

ThreadEvent::ThreadEvent(wxEventType commandType, int id)
: wxEvent( id, commandType )
{
  this->count = 0;
  this->message = wxEmptyString;
}
in the current wx development version the whole event system has been turned upside down to make this typesafe and avoid errors like this ;)

Another thing although it didn't lead to a crash in this particular case. If you intend to send an event from a thread and have a wxString (or any other reference counted object) in your event class you must enforce a deep copy of the string in the Clone() method:

Code: Select all

wxEvent* ThreadEvent::Clone() const { 
  ThreadEvent *newevent=new ThreadEvent(*this);
  newevent->message=this->message.c_str();  // this enforces a deep copy of the string data
  return newevent;
}
Use the source, Luke!

Kraymer
Earned a small fee
Earned a small fee
Posts: 23
Joined: Wed Feb 04, 2009 1:32 pm
Location: Germany
Contact:

Post by Kraymer » Wed May 20, 2009 11:19 am

doublemax wrote:main mistake, wrong order of "id, commandType"
Yes, it was mentioned on IRC too. Thanks anyway!
Looking forward to a hopefully improved (and easier?) event system.
Another thing although it didn't lead to a crash in this particular case. If you intend to send an event from a thread and have a wxString (or any other reference counted object) in your event class you must enforce a deep copy of the string in the Clone() method:

Code: Select all

wxEvent* ThreadEvent::Clone() const { 
  ThreadEvent *newevent=new ThreadEvent(*this);
  newevent->message=this->message.c_str();  // this enforces a deep copy of the string data
  return newevent;
}
Thanks, I'll take this into account.

Post Reply