我有一个应用程序,它混合了WPF和WinForm控件,因为该项目早在WPF可用之前就已经启动了。不可能将所有控件更改为基于WPF的控件,这是因为控件的数量以及需要向后兼容其他构建进一步应用程序的控件。
现在,我偶尔会遇到重入问题,这会导致“集合被修改”异常,因为当我们调用WPF dispatcher消息时,由于其他挂起的WinForms消息,它将导致在发送WPF消息时出现在WinForms端的意外消息泵出。
典型的调用堆栈从WPF调用开始,但最终调用BeginInvoke WinForm消息,这会改变UI的状态。我可以通过事件处理程序来更改WPF集合,该集合此时正在枚举。
…。
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherOperation operation, CancellationToken cancellationToken, TimeSpan timeout)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)但是,实际的WPF仅导致这种情况的代码看起来是无辜的:
UIDispatcher.Current (this is WPF Dispatcher) .Invoke(new Action<string, …>(delegate(string msg, …)
{
this.statusModel.AddToStatus(msg, …);
}), new object[]
{
message,
icon
});
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
….这种行为有记录在案吗?因为我有WinForm和WPF代码,所以有一些基于WinForm的代码使用WinForm机制在uses (ISynchronizeInvoke of System.Windows.Forms.Control)中触发执行。
这基本上混合了WPF和WinForms发送的消息。什么是建议的解决办法,以摆脱这种混乱?如果我通过调用WPF Dispatcher调用来更改所有WinForms调用/BeginInvoke调用,那么我们就有一个通用的消息处理队列,而不是两个。还是有更好的方法?
更新1
混合WPF和WinForms的问题也可以在这里找到更详细的内容:
发布于 2016-02-02 15:35:24
如何嵌套调用,以便从您选择的消息泵中确定地触发所有调用?
就像这样:
yourWinFormsControl.Invoke((Action)(() =>
{
UIDispatcher.Current.Invoke(
(Action)(() =>
{
this.statusModel.AddToStatus(xyz);
}));
}));这将创建一个Action,它在WPF调度程序上执行调用,但将其推送给WinForms调度程序。
https://stackoverflow.com/questions/35156961
复制相似问题