为什么仅在调试时引发跨线程异常

本文关键字:线程 异常 调试 为什么 | 更新日期: 2023-09-27 18:31:12

我有一个小应用程序,它实现了基于 MEF 的插件系统。应用动态加载插件,新插件可以随时放置在插件文件夹中。为了实现这一点,我使用自动重组和事件 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 线程调用上述方法时,就像在主窗体 ctor 中一样,一切都很好。但是一旦我将一个新插件放入插件文件夹中,就会调用此方法,并且在"正常执行"(从VS 2010外部或通过ctrl + F5调用应用程序)时,它似乎可以工作,在列表框中显示新插件,当使用F5(调试)从VS 2010内部调用时, 它会引发异常,bessage 控件"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);
    }
}

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

是否有在调试模式下处于活动状态

的选项来检查在发布模式下未处于活动状态的此类跨线程问题?

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

还是我错过了什么?

提前感谢!

为什么仅在调试时引发跨线程异常

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

可以通过 CheckForIllegalCrossThreadCalls (Control类上公开的静态属性)来控制此行为。我强烈建议不要禁用它,但抛出这些异常是为了让开发人员知道他们的多线程可能存在一些问题(Control派生类不是线程安全的)