invoke vs begininvoke, mdi/child and showdialog

G

Guest

vs2005, c#
Trying to understand why one way works but the other doesnt.
I have not tried to create a simpler mdi/child/showdialog app for posting
purposes (I think even this would not be so small or simple). I am hoping
the description will generate some ideas I can check out.


PROBLEM:
-----------------
Switching to UI thread using Invoke(), everything seems good.
Switching to UI thread using BeginInvoke(), Invoke() call from another
thread hangs.


APPLICATION INFO:
-------------------------------
MDI application.

MDI creates a 2nd thread (th_mdi). th_mdi has an event it fires when it
receives messages.

Multiple identical child windows. Each subscribes to the th_mdi event.
Each uses either Invoke() or BeginInvoke() to switchover to UI thread when
receiving the event. Each displays data received from the event in a
richtextbox.

One child window creates a new (different) form and shows it modally using
ShowDialog(). The new form periodically updates its diplay, via a
backgroundworker. The new form creates its own 2nd thread (th_form).
th_form sends a bunch of data out, then calls the new form to give status. <
for test purposes, the data going out is externally routed back to th_mdi to
cause it to start firing events >
RESULT: (if the th_mdi event uses Invoke()) The new form uses Invoke() to
swithover to the UI thead to display a status message. th_tx then calls
the new form to give a done msg and exits. The new form uses Invoke() to
swithover to the UI thead to update its display then closes itself.
RESULT: (if the th_mdi event uses BeginInvoke()) The new form tries to
Invoke() to switchover to the UI thread, but it hangs here, forever.


VISUAL INFO:
---------------------
When using Invoke(), each child window is updating its displayed data
syncronous with the other child windows (as expected).

When using BeginInvoke(), it starts with the same behavior, but will
eventually change to going round robin between the child windows, updating
each with a number of messages before switching to the next child window.
(would not expect this to matter)

All of the child windows seem to finish receiving messages, and are no
longer updating their displays.

The other form completes sending its data but never closes. It continues to
update its display.


QUESTIONS:
--------------------
Mdi / Child / modal form from ShowDialog..... Is the ShowDialog() having
some interaction that leads to this?

Using BeginInvoke(), when each of the child windows starts processing many
queued event messages at a time (see visual info section), can one of these
messages somehow get lost, and thereby somehow lock the other thread out?


TIA
 
N

Nicholas Paldino [.NET/C# MVP]

From what I gather, it seems like you have a simple deadlock operation.
It appears that you have code that is executed when you marshal the call to
the UI thread which the background worker thread is dependent on completing.
The reason Invoke works is that the call to Invoke waits until the call is
completed on the UI thread. With BeginInvoke, the call is marshaled to the
thread, but then your code continues.

It looks like you are going ahead and executing that code when you
should probably be waiting, as there is state that is dependent in the code
after the call to Invoke/BeginInvoke which is not set.
 
G

Guest

Thanks for the replay.

I mentioned the backgroundworker (which updates the form) for completeness.
I can block starting it up and the problem still occurs.

The Invokes to the UI are updating controls (progress bar, label, rtb) and
exiting. I do not see anything they would be contending for... other than
access to the UI thread.

I was trying to turn off more stuff when I received a null ref exception on
the Invoke() command (pasted further down). Nothing should have been or
appeared to be null. But while looking at this I noticed that the thread was
set as multi apartment vs single apartment. I added the following to the
thread creation sections:
thread_1.ApartmentState = ApartmentState.STA;
So far after switching to STA it is not hanging up.


???
If this is in fact a solution, I am not sure why a MTA thread would be an
issue?
Not sure what was null for the exception. Everything looked ok. ?

exception:
System.NullReferenceException occurred
Message="Object reference not set to an instance of an object."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle
waitHandle)
at System.Windows.Forms.Control.MarshaledInvoke(Control caller,
Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.Invoke(Delegate method)
...... <the line calling Invoke()>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top