I think I'm having a problem when a worker thread creates a Form..

cjard

Well-known member
Joined
Apr 25, 2006
Messages
7,081
Programming Experience
10+
I've had a problem driving me bonkers all day, thinking it was a problem with crystal reports' ReportViewer..

I would make a new form (with an instance of the reportviewer on it) and set the properties to make it show a block of data. It would work, apparently, and investigating with the debugger would show everything correct and present, but the report viewer form would hang shortly after, becoming unresponsive; (Not responding) appears in the titlebar..

Other people have had similar issues (mainly ASP.NET), but no solutions. What bugged me most was that if I started a new project, and repeated the code, it would work..

I now think I may have done something, because in a flash of inspiration, I wondered if the problem was related to the fact that it is a worker thread that creates the form (hence being responsible for the message pumping??) - the new projects, that worked, dont use backgroundworkers and the main ui thread does everything.


See, the worker thread dies naturally, shortly after it has created the form. To test the theory I have put lines of code in to create a variety of other forms on the worker thread, and they all crash too. The app's main form remains responsive, leaving a load of dead child windows all over the place...

I didnt catch onto this initially, because InvokeRequired on various controls always returned false; but of course it will because all it does is compare the ThreadID of the current thread (worker thread), with the thread that created the control (worker thread) and hence its false..

So my question is:

Is creating the form/any GUI elements on the worker thread a dumb thing to do?
Is it the cause of the unresponsive-windows problem?
How do I have the main UI thread create the windows?

Does the worker thread need reference to the UI thread?
How does it get it?
 
(I'm thinking of making the worker support progress reporting, then when it has finished doing database query stuff (a blocking excercise) it can report a progress that will make the main UI thread create the viewer forms. This kind of invokation is built into BackgroundWorker, so it should be quite 'clean' to implement

If anyone has any comment on how it could be done otherwise, do please let me know..)
 
Haven't done much with background workers myself but these seems entirely possible with a simple delegate. Have a Delegate point to a method that does your database stuff, define a routine with the IAsyncResult as a parameter. Call begin invoke on the delegate and pass in the method that takes IAsync result as a parameter, as the callback argument. When the thread has done it's job it will call back the routine that you have defined. There you can check the invoke required property, if necessary begin a new Asynchronus Callback to the same method to merge the child thread main in with the main UI thread, end invoke, run the code to do the opening of the windows etc. Job done. Can't see why it shouldn't work.
 
One thing I've always wondered with this.. how does it know to use the UI thread for such an Invoke? Delegates, afaics, are designed to allow a thread to call a method without knowing its name at design time; what is it that guarantees that the UI thread will call the method that creates the form etc?
 
Back
Top