我正在测试我正在编写的程序,并收到此错误消息:Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created on
代码有点大,我不确定哪个部分导致此错误发布较小的段。但是,这里有一些可能有用的信息。
我没有明确使用任何“线程”。我猜其他东西是自动创建多个线程 - 我正在使用Wii远程硬件访问库,我正在进行图形处理。
堆栈跟踪表明,调用on on change事件处理程序,该处理程序调用一个函数,其中lblStatus
被尝试修改 - 但失败。
我想知道如何调试这些类型的错误。我正在使用Visual Studio 2008。
修改
有一件事我想澄清,我不知道这个不同的线程是如何出现的。我怎么能找到这个?不同主题的来源。
答案 0 :(得分:4)
public void SetStatus(string msg)
{
if (lblStatus.InvokeRequired)
lblStatus.Invoke(new MethodInvoker(delegate
{
lblStatus.Text = msg;
}));
else
lblStatus.Text = msg;
}
这将使您的标签文本更新。
对于BeginInvoke,这是我所知道的方式(我知道有更优雅的实现) - 但我还没有在多线程应用程序中尝试过这个:
Action<string> setStatus= target.AppendText;
void OnSomeEvent (object sender, EventArgs e)
{
IAsyncRes iares = setStatus.BeginInvoke("status message", null, null);
setStatus.EndInvoke(iares);
}
public void SetStatus(string msg)
{ lblStatus.Text = msg; }
对于与控制线程同步的不同方法,SnOrfus引用了一个很好的链接。上面我在BeginInvoke上的示例 not 正确无法同步到控件的线程。
至于导致线程的原因:About WiimoteChanged event
答案 1 :(得分:2)
您无法从主线程以外的任何线程访问可视元素。您需要使用Dispatcher.Invoke()
来调用更新视觉元素的委托。
示例:
this.Dispatcher.Invoke((Action)(() => lblStatus.Content = "Hello"));
或(没有lambda):
this.Dispatcher.Invoke((Action)delegate() { lblStatus.Content = "Hello"; });
答案 2 :(得分:0)
您需要将Delegates的使用与您的线程相结合..
将您的方法分配给委托,然后通过线程调用委托。
答案 3 :(得分:0)
有一件事我想澄清,我不知道这个不同的线程是如何出现的
如果您的应用不是多线程的,则问题可能是由Visual Studio托管过程引起的。 Visual Studio托管进程启动主线程,然后创建运行应用程序的新UI线程。在某些情况下,这可能会导致跨线程异常,例如when accessing Form.ActiveForm before calling Application.Run。
如果这是您的问题,可以在“项目属性”的“调试”选项卡中取消选中“启用Visual Studio主机进程”。