刚刚有了一个想法,我以前没见过,想知道你们是否认为这是一个好主意,是否存在,任何常见的陷阱等等 - 以及如何实现它。
有几次我发现自己订阅了来自UI线程的事件,该事件将从不同的线程调用 - 例如,完成服务调用的通知。
'我'的想法是将当前Dispatcher
与处理程序委托一起存储在add
块中,然后当事件被'触发'时,执行一些额外的逻辑/检查以查看是否有一个与处理程序关联的调度程序,如果需要,还有Invoke
。
当然它只适用于Dispatcher
的线程(或者与Forms相同的东西 - 我猜的是带消息泵的东西)。我想有用性和清洁度取决于事件订阅者是否应该担心调用处理程序的线程?
编辑:听起来这不是一件坏事 - 另外有人知道如何实施吗?使用Delegate.Combine
如何在不同的Dispatcher
上调用每个处理程序?您是否会将委托存储在List
中的复合对象中,并在On(Whatever)
方法中依次调用它们,还是有更好的东西?
...查看Reflector中的BackgroundWorker
源代码,无需调用:
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler handler = (ProgressChangedEventHandler) base.Events[progressChangedKey];
if (handler != null)
{
handler(this, e);
}
}
除非我遗漏了什么?
然后BackgroundWorker
使用AsyncOperation
执行此操作。在事件访问器中,只为事件处理程序提供通用解决方案? BackgroundWorker
可以通过它的工作方式逃脱,因为从客户端调用了一个方法 - 在更一般的情况下,你有权访问处理程序的线程的唯一时间是在事件访问器中? :)
答案 0 :(得分:4)
据我所知,这正是BackgroundWorker
在RunWorkerCompleted
和ProgressChanged
事件中正在做的事情。所以它不能那坏
我找不到真正的证明,BackgroundWorker
正在做这件事,我只是在某处读到它。当您google for it时,您会发现更多提示。如果有人可以提供链接,我会很高兴。
<强>更新强>
因为在BackgroundWorker中找到这种行为并不容易,所以我提供了我的分析:
BackgroundWorker
正在使用AsyncOperation
来举起活动。在此课程中,事件将发布到SynchronizationContext
。只有这样才能执行方法OnProgressChanged
和OnRunWorkerCompleted
。这意味着,这些方法已经在正确的线程上执行。
更详细地说,当调用RunWorkerAsync
时会发生以下情况:
AsyncOperation
实例是通过AsyncOperationManager.CreateOperation
创建的。这样可以保存当前SynchronizationContext
。由于我们仍处于UI线程中,因此这是UI线程的上下文。WorkerThreadStart
。此方法在后台线程中运行并执行OnDoWork
,后者又会引发DoWork
事件。这意味着,在{@ li>中,DoWork
事件在 OnDoWork
完成后,PostOperationCompleted
实例的AsyncOperation
方法会被调用,AsyncOperation.Post
会调用SynchronizationContext.Post
,后者会调用OnRunWorkerCompleted
,后者将间接调用UI线程上的ReportProgress
。AsyncOperation.Post
时,会发生类似的事情:直接调用OnProgressChanged
并在UI线程上调用{{1}}方法。 AsyncOperation
和AsyncOperationManager
是公开的,可用于在您的类中实现类似的行为。
答案 1 :(得分:0)
我已经使用Castle DynamicProxy做了类似的事情,它拦截了调用并对它们进行了IsInvokeRequired/Invoke
。