How to call MessageBox.Show() from a separate thread?
I am writing a multi-thread program in C# .NET in VS2008 and try to call MessageBox.Show method to display a message box in the background thread, see the following code:
// start the updater on a separate thread so that our UI remains responsive
_autoUpdaterThread = new Thread(new ThreadStart(CheckLatestVersion));
_autoUpdaterThread.Start();
.....
private void CheckLatestVersion()
{
try
{
.....
if (string.Compare(latestVersion, curVersion) > 0)
{
DialogResult result = DialogResult.None;
result = MessageBox.Show(this, message, title, MessageBoxButtons.YesNo, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
}
}
When I run my application, a System.InvalidOperationException is thrown with the following information:
Cross-thread operation not valid: Control 'MainForm' accessed from a thread other than the thread it was created on.
Solution
The "this" on the following line in your code is a reference to MainForm. That is why I am getting a cross thread exception.
MessageBox.Show(this, ....
To fix this problem, just use Control.Invoke() to make it modal to the main thread.
// start the updater on a separate thread so that our UI remains responsive
_autoUpdaterThread = new Thread(new ThreadStart(CheckLatestVersion));
_autoUpdaterThread.Start();
.....
private void CheckLatestVersion()
{
try
{
.....
if (string.Compare(latestVersion, curVersion) > 0)
{
DialogResult result = DialogResult.None;
result = ShowMessage(message, title, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
}
catch (Exception ex)
{
}
}
protected delegate DialogResult ShowMessageDelegate(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton);
protected DialogResult ShowMessage(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
DialogResult rtn = DialogResult.None;
if (this.InvokeRequired)
{
ShowMessageDelegate d = new ShowMessageDelegate(ShowMessage);
rtn = (DialogResult)this.Invoke(d, new object[] { message, title, buttons, icon, defaultButton });
}
else
{
rtn = MessageBox.Show(this, message, title, buttons, icon, defaultButton);
}
return rtn;
}