Problem showing message boxes by threads

C

Claire

Hi
I need to set my main form as the owner of an error dialog box shown when
there's an exception in a background thread. This is to make sure that the
error form is closed down if the user pulls their security card while the
error window is being shown.
In visual studio 2003, my main form set a static "owner" variable within my
frmWarning class definition and if the error form was needed (and null owner
passed) then this static variable was used. It's not pretty but it was the
only way I could think of for making sure that error dialogs could be closed
by the main form.
This worked fine when there was an error thrown somewhere in my thread loop
in vis studio 2003.
I've just transferred it all across to 2005 and now my error form won't
appear. If I remove the line that looks for the static owner member variable
then it shows ok. But that's no good because then pulling the card doesnt
shut the form down.
I guess I'm doing something naughty, but is there a way of changing this
following function so that I can use the frmWarning.owner properly plus if
the main form (created by main process) then tries to close the form (that
has been created by the thread) later then that will work fine too.
thank you (hope that was all understandable)
Claire

public static DialogResult ShowError(System.Windows.Forms.IWin32Window
Owner, string ErrorMessage)
{
string fnName = "ShowError";
DialogResult result = DialogResult.OK;
frmWarning frm = new frmWarning();
try
{
frm.lblText.Text = ErrorMessage;
// if (Owner == null) Owner = frmWarning.owner;
result = frm.ShowDialog(Owner);
}
catch (Exception e)
{
Log.Exception(typeof(frmWarning), fnName, e);
}
finally
{
frm.Dispose();
}
return result;
}

/// <summary>
/// Destroy child forms which are owned by the
/// root form. Closing the root alone won't destroy the
/// child forms automatically. All children have to be
/// created by passing their owning form in ShowDialog(Form owner)
/// parameter
/// An iterative function called from main form.
/// </summary>
/// <param name="Root">The base form</param>
static public void DestroyOwned(Form Root)
{
for ( int d=Root.OwnedForms.GetLength(0) - 1; d >= 0; d--)
{
DestroyOwned(Root.OwnedForms[d]);
Root.OwnedForms[d].Close();
}
}// function
 
P

Patrick Steele

Hi
I need to set my main form as the owner of an error dialog box shown when
there's an exception in a background thread.

Windows Forms are not threadsafe. VS2003 let you get away with some
threading stuff that VS2005 won't.

Windows forms objects must be accessed only by the thread that created
them. You can use a delegate along with Control.Invoke to marshal a
call back to the UI thread. Here's a quick example:

// define a delegate the background thread will use
public delegate void UpdateStatusDelegate(string message);

// in our form, define a method that will update status text
// NOTE: this method matches the signature of our delegate
public void UpdateStatus(string statusMessage)
{
txtStatus.Text = statusMessage;
}

With the above in place, you can now safely update the "txtStatus"
control from a different thread by wrapping the call in a delegate. In
your background thread, do this:

UpdateStatusDelegate upd = new UpdateStatusDelegate(UpdateStatus);
this.Invoke(upd);

This will marshal the call to UpdateStatus back to the UI thread where
it will execute sucessfully.

This is a simple example that you'll need to extend to your app. Any
manipulation of a form (closing, updating controls, moving, etc...) must
be done in the main UI thread (the thread that created the control).
 

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