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

Jau*_*uch 4 c# debugging multithreading mef winforms

我有一个小应用程序,实现了基于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);
}
Run Code Online (Sandbox Code Playgroud)

当从UI线程调用上述方法时,就像在Main Form ctor中一样,一切都很好.但是,只要我在插件文件夹中放置一个新插件,就会调用此方法,并且在"正常执行"(从VS 2010外部或通过ctrl + F5调用应用程序)时,它似乎正常工作,显示在列表框是新插件,当使用F5(调试)从VS 2010内部调用时,它会引发一个异常,其中包含从其创建的线程以外的线程访问的控件'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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

是否存在在调试模式下处于活动状态的选项,以检查在发布模式下未激活的此类交叉线程问题?

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

或者我错过了什么?

提前致谢!

Ale*_*lex 7

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

可以通过CheckForIllegalCrossThreadCalls(Control类上公开的静态属性)来控制此行为.我强烈建议不要禁用它,但是这些异常会让开发人员知道他们的多线程可能有些错误(Control导致的类不是线程安全的)