65.9K
CodeProject 正在变化。 阅读更多。
Home

基于TPL Dataflow库的同步上下文

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2012年10月9日

CPOL

2分钟阅读

viewsIcon

12805

有时,为了演示或测试目的,我需要一个同步上下文,其行为类似于用户界面上下文,但不需要我构建具有用户界面的应用程序,而TPL Dataflow库似乎是实现这种同步上下文的理想选择。

SynchronizationContext实现的同步模型的目的是允许公共语言运行时的异步/同步操作与不同的同步模型正确地协同工作。此模型还简化了托管应用程序为了在不同的同步环境下正确工作而必须遵循的一些要求。此类同步环境的示例包括用户界面基础结构,例如Windows 窗体Windows Presentation FoundationASP.NETStatCounter

同步模型提供程序扩展此类以提供其自己的实现。因为这些用户界面基础结构通常在其自己的线程上运行,所以将执行调度到其执行上下文通常意味着离开当前线程。

任务并行库 (TPL)提供数据流组件来帮助提高并发启用应用程序的健壮性。这些数据流组件统称为TPL Dataflow库。此数据流模型通过为粗粒度数据流和流水线任务提供进程内消息传递来促进基于参与者的编程。数据流组件建立在TPL的类型和调度基础结构之上,并与C#、Visual Basic和F#语言对异步编程的支持集成在一起。当您有多个操作必须彼此异步通信,或者当您希望在数据可用时处理数据时,这些数据流组件非常有用。

TPL Dataflow库 (System.Threading.Tasks.Dataflow命名空间)未与.NET Framework 4.5一起分发。要安装System.Threading.Tasks.Dataflow命名空间,请在Visual Studio 2012中打开您的项目,从项目菜单中选择管理NuGet包,然后在线搜索Microsoft.Tpl.Dataflow包

有时,为了演示或测试目的,我需要一个同步上下文,其行为类似于用户界面上下文,但不需要我构建具有用户界面的应用程序,而TPL Dataflow库似乎是实现这种同步上下文的理想选择。

它就这么简单

public class TplDataflowSynchronizationContext : SynchronizationContext
{
    private ActionBlock<actionitem> ab
        = new ActionBlock<actionitem>(
            item =>
            {
                Trace.WriteLine(
                    string.Format("{0}: {1}", Environment.CurrentManagedThreadId, item.operation));

                try
                {
                    item.d(item.state);
                }
                finally
                {
                    item.SetResult(true);
                }
            });

    public override SynchronizationContext CreateCopy()
    {
        return new TplDataflowSynchronizationContext();
    }

    public override void Post(SendOrPostCallback d, object state)
    {
        Trace.WriteLine(
            string.Format("{0}: Posting...", Environment.CurrentManagedThreadId));

        this.ab.Post(new ActionItem { d = d, state = state, operation = "Post" });

        Trace.WriteLine(
            string.Format("{0}: Posted.", Environment.CurrentManagedThreadId));
    }

    public override void Send(SendOrPostCallback d, object state)
    {
        Trace.WriteLine(
            string.Format("{0}: Sending...", Environment.CurrentManagedThreadId));

        ActionItem item = new ActionItem { d = d, state = state, operation = "Send" };
        this.ab.SendAsync(item);
        item.Task.Wait();

        Trace.WriteLine(
            string.Format("{0}: Sent.", Environment.CurrentManagedThreadId));
    }

    public class ActionItem : TaskCompletionSource<bool>
    {
        public SendOrPostCallback d;
        public object state;
        public string operation;
    }
}

更新:修复了实现,因为SynchronizationContext.Send方法在完全执行操作之前就返回了。感谢Svick指出这一点,并感谢Stephen Toub的帮助修复了它。

© . All rights reserved.