使用Invoke()时的跨线程异常

时间:2015-02-27 08:46:20

标签: c# winforms windows-mobile-5.0 motorola-emdk smart-device-framework

我正在开发一个在基于Windows Mobile 5的条形码扫描仪上运行的应用程序。偶尔我遇到一个跨线程异常导致应用程序失败。

该应用程序是用C#3.5编写的,它构建于Motorola EMDK for .NET之上,但也使用Smart Device Framework的部分内容。

在我的主窗体中,我有一个Panel,我根据应用程序的上下文更改内容。所有视图共享一个公共接口IContentView。

我还使用一些后台线程来监控设备当前是否正在充电(触发用户注销),还监控设备是否可以连接到服务器。

我在调用Panel上的更改时使用here中的John Skeets构造,以确保在要更改的控件上调用更改:

    public void ShowContent(IContentView content)
    {
        contentPanel.Invoke(() =>
            {
                contentPanel.Controls.Clear();
                contentPanel.Controls.Add(content as UserControl);
                contentPanel.Focus();
            });
    }

contentPanel是一个System.Windows.Forms.Panel。

但我仍然遇到以下异常:

Control.Invoke must be used to interact with controls created on a separate thread.
   at Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
   at System.Windows.Forms.Control.get_Parent()
   at System.Windows.Forms.Control.ControlCollection.Add(Control value)
   at BarcodeScanner.MainView.MainForm.<>c__DisplayClass1e.<ShowContent>b__1d()
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Windows.Forms.Control.TASK.Invoke()
   at System.Windows.Forms.Control._InvokeAll()
   at System.Windows.Forms.Control.WnProc(WM wm, Int32 wParam, Int32 lParam)
   at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
   at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
   at System.Windows.Forms.Application.Run(Form fm)
   at BarcodeScanner.Program.Main()

我在这里缺少什么?我是否需要做其他事情来正确地从线程到面板编组更改?

任何建议都非常感谢。

1 个答案:

答案 0 :(得分:2)

对我来说,似乎在将content as UserControl添加到Controls时会出现问题。

检查创建了哪个线程IContentView content,我想不在主线程中,这可能是问题所在。

另见:Why can you cross thread adding controls in WinForms, but not WPF?

因此,似乎这在Windows窗体中也是“禁止的”,但不是由框架代码严格检查。

所以解决方案是在主线程中创建所有GUI控件,可能也使用Invoke()