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

fli*_*ubt 27 c# multithreading conceptual synchronizationcontext threadpool

感谢Jeremy Miller在日常.NET开发的功能编程方面所做的出色工作,我有一个工作的命令执行器,它可以完成我想要的所有工作(对线程池进行繁重的工作,将结果或错误发送回同步环境,甚至发布进度回同步上下文),但我无法解释为什么它使用SynchronizationContext.Send从线程池和Synchronization.PostFunc传递到了做繁重的方法.我已经多次阅读过这些文档,但我对于它的不同之处并不是很有道理.我应该从一个叫做Send一个叫做一个被调用的事实中获得什么Post?我觉得魔术是Send"启动同步请求"和Post"启动异步请求" 这一事实,但这两个请求都来自线程池,需要发送/发回到UI线程.

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

在如此重要的情况下,这是我的测试代码,我用Post发进度回UI:

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);
}
Run Code Online (Sandbox Code Playgroud)

_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));
         }
     });
}
Run Code Online (Sandbox Code Playgroud)

Hen*_*man 30

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

后异步:下拉并继续

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

  • 容易记住:你不要等待`Post`,你只希望它会传递你的信息. (3认同)
  • 我仍然对此感到困惑.我认为同步上下文为您提供了一种在UI线程上做一些工作的简单方法,所以您不必等待它吗?或者它是这样工作的:你在后台线程做一些工作,在中间你需要做一些UI工作,然后继续在后台线程.如果您使用发送,后台线程不会继续到第2部分,直到UI工作完成,但是如果您使用Post后台线程将继续工作而无需等待UI线程工作? (2认同)