如何在.NET中调试跨线程异常?

时间:2010-02-20 07:04:26

标签: c# multithreading debugging

我正在测试我正在编写的程序,并收到此错误消息: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。

修改

有一件事我想澄清,我不知道这个不同的线程是如何出现的。我怎么能找到这个?不同主题的来源。

4 个答案:

答案 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主机进程”。