【发布时间】:2012-07-01 05:45:22
【问题描述】:
简而言之,我实现了一个派生自 SynchronizationContext 的类,以使 GUI 应用程序可以轻松地使用在 GUI 线程以外的线程上引发的事件。我非常感谢 cmets 在我的实施中。具体来说,您有什么建议反对或可能导致我没有预见到的问题吗?我的初步测试已经成功。
长版: 我目前正在开发分布式系统 (WCF) 的业务层,该系统使用回调将事件从服务器传播到客户端。我的设计目标之一是提供可绑定的业务对象(即 INotifyPropertyChanged/IEditableObject 等),以便在客户端轻松使用这些对象。作为其中的一部分,我提供了一个回调接口的实现,它在事件进入时处理它们,更新业务对象,进而引发属性更改事件。因此,我需要在 GUI 线程上引发这些事件(以避免跨线程操作异常)。因此,我尝试提供一个自定义 SynchronizationContext,实现回调接口的类使用它来将事件传播到 GUI 线程。另外,我希望这个实现独立于客户端环境——例如WinForms GUI 应用程序或 ConsoleApp 或其他东西。换句话说,我不想假设静态 SynchronizationContext.Current 可用。因此,我使用 ExecutionContext 作为后备策略。
public class ImplicitSynchronisationContext : SynchronizationContext
{
private readonly ExecutionContext m_ExecContext;
private readonly SynchronizationContext m_SyncContext;
public ImplicitSynchronisationContext()
{
// Default to the current sync context if available.
if (SynchronizationContext.Current != null)
{
m_SyncContext = SynchronizationContext.Current;
}
else
{
m_ExecContext = ExecutionContext.Capture();
}
}
public override void Post(SendOrPostCallback d, object state)
{
if (m_SyncContext != null)
{
m_SyncContext.Post(d, state);
}
else
{
ExecutionContext.Run(
m_ExecContext.CreateCopy(),
(object args) =>
{
ThreadPool.QueueUserWorkItem(new WaitCallback(this.Invoker), args);
},
new object[] { d, state });
}
}
public override void Send(SendOrPostCallback d, object state)
{
if (m_SyncContext != null)
{
m_SyncContext.Send(d, state);
}
else
{
ExecutionContext.Run(
m_ExecContext.CreateCopy(),
new ContextCallback(this.Invoker),
new object[] { d, state });
}
}
private void Invoker(object args)
{
Debug.Assert(args != null);
Debug.Assert(args is object[]);
object[] parts = (object[])args;
Debug.Assert(parts.Length == 2);
Debug.Assert(parts[0] is SendOrPostCallback);
SendOrPostCallback d = (parts[0] as SendOrPostCallback);
d(parts[1]);
}
}
【问题讨论】:
-
多线程难,我们去购物+1(好问题)
标签: c# .net multithreading