为什么只有在调试时才会引发跨线程异常?

时间:2013-09-12 11:12:38

标签: c# multithreading winforms debugging mef

我有一个小应用程序,它实现了一个基于MEF的插件系统。 应用程序加载动态插件,并且可以随时将新插件放在plugins文件夹中。 为了实现这一点,我使用自动重组和事件Changed,当新部件可用时,它会引发。 当某些新部件可用时,我会更新UI中的列表框。

导致问题的代码是在Changed事件触发时调用的方法:

public void OnUserViewPluginCatalogChanged
             (object sender, ComposablePartCatalogChangeEventArgs e)
{
    listBox1.Items.Clear();
    foreach (var item in fPluginStore.PluginsAvailable)
        listBox1.Items.Add(item.Metadata["Caption"] as string);
}

当从UI线程调用上述方法时,就像在Main Form ctor中一样,一切都很好。但是,只要我在插件文件夹中放置一个新插件,就会调用此方法,并且在“正常执行”(从VS 2010外部或通过ctrl + F5调用应用程序)时,它似乎正常工作,显示在列表框是新插件,当使用F5(调试)从VS 2010内部调用时,它会引发一个异常,其中包含从创建的线程以外的线程访问的bessage Control'listbox1'。

我通过以下代码解决了这个问题:

public void OnUserViewPluginCatalogChanged
             (object sender, ComposablePartCatalogChangeEventArgs e)
{
    if( listBox1.InvokeRequired )
    {            
        this.Invoke((MethodInvoker) delegate { listBox1.Items.Clear(); });
        foreach (var item in fPluginStore.PluginsAvailable)
            this.Invoke((MethodInvoker) delegate 
                        {listBox1.Items.Add(item.Metadata["Caption"] as string);});
    }
    else
    {    
        listBox1.Items.Clear();
        foreach (var item in fPluginStore.PluginsAvailable)
           listBox1.Items.Add(item.Metadata["Caption"] as string);
    }
}

我的问题是为什么仅在调试模式下引发异常?

是否有一个选项在调试模式处于活动状态时检查这种在发布模式下无效的交叉线程问题?

我假设问题出在释放模式中,但由于某种原因它没有显示,因为没有被检查。

或者我错过了什么?

提前致谢!

1 个答案:

答案 0 :(得分:7)

仅检查调试器附加到进程的那些异常,因此在没有调试的情况下(或在VS外部独立)运行进程时它们不会显示。

此行为可以通过CheckForIllegalCrossThreadCalls控制,{{3}}是Control类上公开的静态属性。我强烈建议不要禁用它,但是这些异常会让开发人员知道他们的多线程可能存在非常错误(Control - 派生类线程安全)< / p>