我有一个winforms应用程序,问题与线程有关.因为我调用'MyCustomCode()来创建一个新线程,并调用方法'SomeMethod()'然后访问MessageBox.Show(...).
问题与线程有关,因为新创建的线程正在尝试访问在另一个线程上创建的控件.
我收到错误:
跨线程操作无效:控制'TestForm'从其创建的线程以外的线程访问.
public TestForm()
{
InitializeComponent();
// custom code
//
MyCustomCode();
}
public void SomeMethod()
{
// ***** This causes an error ****
MessageBox.Show(this,
ex.Message,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
private void InitializeAutoUpdater()
{
// Seperate thread is spun to keep polling for updates
ThreadStart ts = new ThreadStart(SomeMethod);
pollThread = new Thread(ts);
pollThread.Start();
}
Run Code Online (Sandbox Code Playgroud)
更新
如果你看一下这个例子http://www.codeproject.com/KB/cs/vanillaupdaterblock.aspx,CheckAndUpdate方法正在调用MessageBox.Show(..),这就是我的问题所在.我本以为代码很好用!
有趣的是,这个代码在星期五工作得很好???
您无法从多个线程访问UI元素.
解决此问题的一种方法是使用UI元素(如消息框)调用具有委托的控件的Invoke方法.有些喜欢:
public delegate void InvokeDelegate();
public void SomeMethod()
{
button1.Invoke((InvokeDelegate)doUIStuff);
}
void doUIStuff()
{
MessageBox.Show(this,
ex.Message,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
Run Code Online (Sandbox Code Playgroud)
为了避免跨线程异常(InvalidOperationException),这里是代码模式:
protected delegate void someGuiFunctionDelegate(int iParam);
protected void someGuiFunction(int iParam)
{
if (this.InvokeRequired)
{
someGuiFunctionDelegate dlg = new
someGuiFunctionDelegate(this.someGuiFunction);
this.Invoke(dlg, new object[] { iParam });
return;
}
//do something with the GUI control here
}
Run Code Online (Sandbox Code Playgroud)
我同意这很烦人,但它是Windows GUI控件不是线程安全的事实.可以通过某处或其他地方的标志关闭该异常,但不要这样做,因为它可能导致极难找到错误.