长话短说: 我目前正在开发一个分布式系统(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]);
}
}