我正在开发一个在基于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()
我在这里缺少什么?我是否需要做其他事情来正确地从线程到面板编组更改?
任何建议都非常感谢。
答案 0 :(得分:2)
对我来说,似乎在将content as UserControl
添加到Controls
时会出现问题。
检查创建了哪个线程IContentView content
,我想不在主线程中,这可能是问题所在。
另见:Why can you cross thread adding controls in WinForms, but not WPF?
因此,似乎这在Windows窗体中也是“禁止的”,但不是由框架代码严格检查。
所以解决方案是在主线程中创建所有GUI控件,可能也使用Invoke()