Threading, InvokeRequired

G

gilles27

I have an exception handling procedure which displays an error message
to the user. This is done by creating an instance of the custom form
ErrorDisplay and showing that instance as a modal dialog, parented to
the main MDI window. The code is as follows.

Private Shared Sub DisplayExceptionMessage(ByVal ToDisplay As String)
Dim frmError As New ErrorDisplay(ToDisplay)
frmError.StartPosition = FormStartPosition.CenterScreen
If frmError.ShowDialog(MdiParent) = DialogResult.No Then
Application.Exit()
End If
End Sub

This procedure normally runs on the main thread, however I have
recently introduced multithreading to the application and am now
finding that it will sometimes run on one of the worker threads I have
created.

The problem comes when showing the error form as its behaviour is not
exactly the same as when the procedure runs from the main thread. I
believe this is because the MdiParent variable, which is a reference to
the app's MDI window, was created on the main thread and frmError on
the worker thread. I probably need to use the Control.Invoke method
here but can't quite see how. This theory is backed up by the fact that
MdiParent.InvokeRequired returns true when running on the worker
thread.

Any suggestions would be gratefully received.

Thanks,

Ross
 
M

Mehdi

Private Shared Sub DisplayExceptionMessage(ByVal ToDisplay As String)
Dim frmError As New ErrorDisplay(ToDisplay)
frmError.StartPosition = FormStartPosition.CenterScreen
If frmError.ShowDialog(MdiParent) = DialogResult.No Then
Application.Exit()
End If
End Sub
[...]
The problem comes when showing the error form as its behaviour is not
exactly the same as when the procedure runs from the main thread. I
believe this is because the MdiParent variable, which is a reference to
the app's MDI window, was created on the main thread and frmError on
the worker thread. I probably need to use the Control.Invoke method
here but can't quite see how. This theory is backed up by the fact that
MdiParent.InvokeRequired returns true when running on the worker
thread.

Sorry, i don't know VB enough to give you a VB sample but you shouldn't
have too much trouble translating this C# code in VB.

It's quite simple actually: check in your DisplayExceptionMessage method if
you are in the UI thread and, if not, call the Invoke method of any UI
control (i chose to call it on MdiParent but you can call it on any other
UI control as long as their handle have been created, the result will be
the same) passing as a parameter a delegate to the method you want to
execute in the UI thread (in your case, it's the DisplayExceptionMessage
method). That's it.



private delegate void DisplayExceptionMessageDelegate(string ToDisplay);

private static void DisplayExceptionMessage(string ToDisplay)
{
if (MdiParent.InvokeRequired)
{
// We are in a worker thread
// and need to marshall ourself
// to the UI thread
DisplayExceptionMessageDelegate deleg = new
DisplayExceptionMessageDelegate(DisplayExceptionMessage);
MdiParent.Invoke(deleg, new object[] {ToDisplay});
}
else
{
// We are now in the UI thread
// Display the error form
ErrorDisplay frmError = new ErrorDisplay(ToDisplay);
frmError.StartPosition = FormStartPosition.CenterScreen;
if (frmError.ShowDialog(MdiParent) == DialogResult.No)
{
Application.Exit();
}
}
}
 
C

Clamps

try this :

Public Delegate delDisplayExceptionMessage
Private Shared Sub DisplayExceptionMessage(ByVal ToDisplay As String)
if me.invokerequired then
dim del as new deldisplayexceptionmessage(ToDisplay)
del.invoke()
else
Dim frmError As New ErrorDisplay(ToDisplay)
frmError.StartPosition = FormStartPosition.CenterScreen
If frmError.ShowDialog(MdiParent) = DialogResult.No Then
Application.Exit()
End If
end if
end sub
 

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