使用Application.Run的多个GUI线程导致跨线程异常

时间:2013-03-16 16:35:17

标签: c# multithreading winforms exception

我有一个C#WinForms应用程序,它包含一个运行时表单设计器/实时数据查看器。用户可以在应用程序运行时添加控件并查看实时数据。它使用了许多第三方图形和仪表类型控件,这些控件在重绘期间非常耗费GUI。设计器表单使用另一个具有属性网格控件的浮动窗体,以允许更改每个用户添加控件的属性。

为了在使用多个设计器时帮助提高应用程序的性能,我使用与此类似的代码将每个表单移动到一个单独的GUI线程:

Thread guiThread = new Thread(CreateScreen);
guiThread.SetApartmentState( ApartmentState.STA);
guiThread.Start();


List<frmDesigner> designers = new List<frmDesigner>(); 
private void CreateScreen()
{  
    frmDesigner designer = new frmDesigner(openedFile, comms);
    designers.Add(designer);
    Application.Run(designer);        
}

这适用于第一个创建的frmDesigner。我可以使用第二种形式的属性网格编辑表单上的所有控件。注意:属性网格表单是从创建设计器的线程打开的。每个frmDesigner都有自己的属性编辑器表单。分享一个会很好,但这会产生更多的麻烦。

如果我创建了多个frmDesigner(每个都在自己的线程中),则在尝试修改控件的BackColor时,所有后续属性网格都会抛出一个跨线程异常。如果我双击属性网格中的颜色选择器,颜色将更改,没有任何异常。可以使用相同的属性网格编辑任何其他属性。我使用Thread.CurrentThread.ManagedThreadId属性验证了所使用的所有表单和控件都在同一个线程上。

我正在尝试了解如何识别导致交叉线程异常的原因。据我所知,所有形式和控件都是在同一个帖子中创建的。

有人询问有关List是线程安全的问题。我只使用主GUI线程中的列表来允许在应用程序退出时关闭设计器。它不会在应用程序的任何其他位置使用。

private void CloseScreens()
    {
        List<frmDesigner> designersToClose = new List<frmDesigner>(); 
        foreach (frmDesigner designer in designers)
        {
            if (designer != null && designer.IsDisposed == false)
            {
                designer.Invoke(new Action(() => { designer.Close(); }));
                designersToClose.Add(designer);
            }
        }

        foreach (frmDesigner designer in designersToClose)
        {
            designers.Remove(designer);
        }
        designers.Clear();
    }

我设法通过在调试选项中关闭“Just my Code”来获取代码。我现在有以下堆栈跟踪。

    System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() + 0xc4 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.SendMessage(int msg, int wparam, ref System.Windows.Forms.NativeMethods.RECT lparam) + 0x10 bytes 
System.Windows.Forms.dll!System.Windows.Forms.TabControl.GetTabRect(int index) + 0x84 bytes 
System.Drawing.Design.dll!System.Drawing.Design.ColorEditor.ColorUI.AdjustColorUIHeight() + 0x3b bytes  
System.Drawing.Design.dll!System.Drawing.Design.ColorEditor.ColorUI.Start(System.Windows.Forms.Design.IWindowsFormsEditorService edSvc, object value) + 0x2f bytes  
System.Drawing.Design.dll!System.Drawing.Design.ColorEditor.EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value) + 0x89 bytes    
System.Windows.Forms.dll!System.Windows.Forms.PropertyGridInternal.GridEntry.EditPropertyValue(System.Windows.Forms.PropertyGridInternal.PropertyGridView iva) + 0x5a bytes 
System.Windows.Forms.dll!System.Windows.Forms.PropertyGridInternal.PropertyDescriptorGridEntry.EditPropertyValue(System.Windows.Forms.PropertyGridInternal.PropertyGridView iva) + 0x17 bytes   
System.Windows.Forms.dll!System.Windows.Forms.PropertyGridInternal.PropertyGridView.PopupDialog(int row) + 0x680 bytes  
System.Windows.Forms.dll!System.Windows.Forms.PropertyGridInternal.PropertyGridView.OnBtnClick(object sender, System.EventArgs e) + 0x6b bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.OnClick(System.EventArgs e) + 0x70 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Button.OnClick(System.EventArgs e) + 0x4a bytes   
System.Windows.Forms.dll!System.Windows.Forms.PropertyGridInternal.DropDownButton.OnClick(System.EventArgs e) + 0xe bytes   
System.Windows.Forms.dll!System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs mevent) + 0xac bytes 
System.Windows.Forms.dll!System.Windows.Forms.PropertyGridInternal.DropDownButton.OnMouseUp(System.Windows.Forms.MouseEventArgs e) + 0xe bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseUp(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0x28f bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x885 bytes 
System.Windows.Forms.dll!System.Windows.Forms.ButtonBase.WndProc(ref System.Windows.Forms.Message m) + 0x127 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Button.WndProc(ref System.Windows.Forms.Message m) + 0x20 bytes   
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x57 bytes 
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason, int pvLoopData) + 0x24e bytes  
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x177 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes  
MDIMain.CreateScreen() Line 282 + 0x8 bytes C#
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   

有没有人知道为什么会根据堆栈跟踪发生这种情况?

0 个答案:

没有答案