SynchronizationContext.Send和SynchronizationContext.Post有什么区别?

时间:2010-03-18 20:15:53

标签: c# multithreading threadpool conceptual synchronizationcontext

感谢Jeremy Miller在Functional Programming For Everyday .NET Development中所做的出色工作,我有一个工作的命令执行器,可以完成我想要的任务(对线程池进行繁重的工作,将结果或错误发送回同步环境,甚至将进度发布回同步上下文),但我无法解释为什么它使用来自线程池的SynchronizationContext.Send而来自Func的{​​{3}}传递给执行繁重工作的方法。我已经多次阅读过这些文档,但我对于它的不同之处并不是很有道理。我应该从一个名为Send而一个名为Post的事实中获得什么?我感觉到神奇的是Send“启动同步请求”而Post“启动异步请求”,但两个请求都来了从线程池中,需要发送/发回到UI线程。

有人可以解释这个区别,即使它只是一个助记符设备让我知道何时选择一个而不是另一个?

如果重要,这是我的测试代码,我使用Post将进度发送回用户界面:

private Action _ExecuteCommand
                (SynchronizationContext context
                 , Action<int, int> progress
                 , Action<int, int> after)
{
    int count = 3;
    int accumulatedValue = 0;
    int threadId = Thread.CurrentThread.ManagedThreadId;
    for (int i = 0; i < count; i++)
    {
        Thread.Sleep(1000);
        context.Post(delegate { progress(i + 1, threadId); });
        accumulatedValue += i;
    }

    return () => after(threadId, accumulatedValue);
}

_ExecuteCommand方法作为command参数传入,主要来自原始文章,使用Send将完成和错误消息发送回UI:

public void Execute(Func<Action> command, Action<Exception> error)
{
    ThreadPool.QueueUserWorkItem(o =>
     {
         try
         {
             Action continuation = command();
             _Context.Send(s => continuation());
         }
         catch (Exception e)
         {
             _Context.Send(s => error(e));
         }
     });
}

1 个答案:

答案 0 :(得分:29)

发送 - 同步:等待回答(或行动已完成)

后 - 异步:退出并继续

因此,您的示例在正确的时刻使用了正确的方法。在进度更新完成之前,没有必要暂停for循环(相反) 并且Execute确实希望等待Action完成,否则异常处理没有任何意义。