CheckForIllegalCrossThreadCalls =的分歧

时间:2010-04-06 20:11:09

标签: c# visual-studio-2008 thread-safety

我最近更新了从VS2003到VS2008的应用程序,我知道我将处理一系列“跨线程操作无效:控制'myControl'从一个线程访问,而不是它创建的线程”我是在我相信的方式处理这是正确的方法(参见下面的代码示例)。我遇到了许多需要类似修复的控件。不希望为非UI线程访问的每个标签,文本框等都有类似的代码。仅为整个应用设置 CheckForIllegalCrossThreadCalls = false 有什么后果?

我发现了一篇CodeProject文章,其中包含各种解决方法,并在底部发出警告,未设置该属性。我正在寻找关于这个问题的其他意见/经验。

private void ShowStatus(string szStatus)
{
    try
    {
        if (this.statusBar1.InvokeRequired) { BeginInvoke(new MethodInvoker(delegate() { ShowStatus(szStatus); })); }
        else { statusBar1.Panels[0].Text = szStatus; }
    }
  catch (Exception ex)
  {
    LogStatus.WriteErrorLog(ex, "Error", "frmMNI.ShowStatus()");
  }
}

我发现了另一篇文章,其中包含一些可能的解决方案SO Question 2367718

2 个答案:

答案 0 :(得分:5)

当你没有调试时,你仍然会遇到问题。

来自Control.CheckForIllegalCrossThreadCalls的文档:

  

请注意,在调试器外部启动应用程序时,非法的跨线程调用将始终引发异常。

你需要纠正这些问题。

话虽如此,你提到:

  

不希望为非UI线程访问的每个标签,文本框等都有类似的代码。

我会重新考虑这个立场。您应该尝试将在单独线程上运行的逻辑移动到单独的方法或类中,这反过来会使调用回调到UI更加简单。随着时间的推移,这将使您的代码更加可靠和可维护。

请注意,您也可以使用Control.Invoke在一次调用中封送对UI的一整套调用,而不是单独执行每个单独的set操作。当你完成时,确实不应该有那么多。

修改

例如,听起来你正在加载数据。假设你有(在你的后台线程上)你的数据加载方法:

var myData = LoadData();
this.Invoke( new Action( () =>
    {
        // Just set all of your data in one shot here...
        this.textBox1.Text = myData.FirstName;
        this.textBox2.Text = myData.LastName;
        this.textBox3.Text = myData.NumberOfSales.ToString();
    }));

答案 1 :(得分:3)

documentation for CheckForIllegalCrossThreadCalls的备注部分清楚地说明这样做不是一个好主意

  

当创建以外的线程时   控件的线程试图访问   其中一个控件的方法或   属性,它经常导致   不可预知的结果。普通的   无效的线程活动是一个调用   访问的错误线程   控制的处理属性。组   CheckForIllegalCrossThreadCalls到   如果找到并诊断此线程,则为true   调试时更容易活动。   请注意非法的跨线程调用   当a时总会引发异常   申请是在外面开始的   调试器。