SynchronizationContext

SynchronizationContext

简而言之,我实现了一个从SynchronizationContext派生的类,以使GUI应用程序可以轻松使用在非GUI线程上引发的事件。我非常感谢您对自己的实现发表评论。具体来说,您有什么建议不对,或者可能导致我没有预料到的问题?我的初步测试已经成功。

长版:
我目前正在开发使用回调将事件从服务器传播到客户端的分布式系统(WCF)的业务层。我的设计目标之一是提供可绑定(bind)的业务对象(即INotifyPropertyChanged/IEditableObject等),以使其易于在客户端使用。作为此过程的一部分,我提供了一个回调接口(interface)的实现,该接口(interface)可以处理事件的发生,更新业务对象,进而引发属性更改的事件。因此,我需要在GUI线程上引发这些事件(以避免跨线程操作异常)。因此,我尝试提供一个自定义的SynchronizationContext,供实现回调接口(interface)的类用来将事件传播到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]);
}

}

最佳答案

不幸的是,您写了一些已经存在的东西。 SynchronizationContext类完全可以完成您的工作。将一个属性添加到您的主类,类似于以下内容:

    public static SynchronizationContext SynchronizationContext {
        get {
            if (SynchronizationContext.Current == null) {
                SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            }
            return SynchronizationContext.Current;
        }
    }

或使用AsyncOperationManager.SynchronizationContext,它做的完全相同。当然是可取的。

关于c# - 源自SynchonizationContext,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3944498/

10-11 00:10