简体   繁体   English

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

[英]What is the difference between SynchronizationContext.Send and SynchronizationContext.Post?

Thanks to Jeremy Miller's good work in Functional Programming For Everyday .NET Development , I have a working command executor that does everything I want it to (do heavy lifting on the thread pool, send results or errors back to the synchronization context, and even post progress back to the synchronization context), but I can't explain why it uses SynchronizationContext.Send from the thread-pool and Synchronization.Post from the Func passed into the method that does the heavy lifting. 感谢Jeremy Miller在日常.NET开发的功能编程方面所做的出色工作,我有一个工作的命令执行器,它可以完成我想要的所有工作(对线程池进行繁重的工作,将结果或错误发送回同步环境,甚至发布进度回同步上下文),但我无法解释为什么它使用SynchronizationContext.Send从线程池和Synchronization.PostFunc传递到了做繁重的方法。 I have read the documentation, several times, but I just can't get a gut sense for what the difference is. 我已经多次阅读过这些文档,但我对于它的不同之处并不是很有道理。 What am I supposed to get from the fact that one is called Send and one is called Post ? 我应该从一个名为Send的事实中得到什么,一个叫做Post I sense the magic is in the fact Send "starts a synchronous request" and Post "starts an asynchronous request", but both requests come from the thread pool and need to be sent/posted back to the UI thread. 我感觉神奇的是Send “启动同步请求”和Post “启动异步请求”,但这两个请求都来自线程池,需要发送/发回到UI线程。

Can someone explain the difference, even if it is just a mnemonic device that lets me know when to choose one over the other? 有人可以解释这个区别,即使它只是一个助记符设备,让我知道何时选择一个而不是另一个?

In case it matters, this is my test code where I use Post to send progress back to the 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);
}

That _ExecuteCommand method is passed in as the command parameter below, mostly from the original article, that uses Send to send completion and error message back to the UI: _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));
         }
     });
}

Send - synchronous: wait for answer (or action completed) 发送 - 同步:等待回答(或动作完成)

Post - asynchronous: drop off and continue 后异步:下拉并继续

So your example uses the correct methods at the right moments. 因此,您的示例在正确的时刻使用正确的方法。 There is no need to halt the for-loop until the progress update is complete (on the contrary). 在进度更新完成之前,无需停止for循环(相反)。
And Execute does want to wait for the Action to complete, otherwise the exception handling has no purpose. 并且Execute确实要等待Action完成,否则异常处理没有任何意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM