【问题标题】:What is the difference between SynchronizationContext.Send and SynchronizationContext.Post?SynchronizationContext.Send 和 SynchronizationContext.Post 有什么区别?
【发布时间】:2015-05-06 23:26:32
【问题描述】:

感谢 Jeremy Miller 在Functional Programming For Everyday .NET Development 中的出色工作,我有一个工作命令执行器,它可以完成我想要它做的所有事情(对线程池进行繁重的工作,将结果或错误发送回同步上下文,甚至发布进度回到同步上下文),但我无法解释为什么它使用来自线程池的SynchronizationContext.Send 和来自FuncSynchronization.Post 传递到执行繁重工作的方法中。我已多次阅读文档,但我无法直观地了解其中的区别。我应该从一个叫做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);
}

_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));
         }
     });
}

【问题讨论】:

  • 它们的名字真的很糟糕。

标签: c# multithreading threadpool conceptual synchronizationcontext


【解决方案1】:

发送 - 同步:等待应答(或操作完成)

后 - 异步:放下并继续

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

【讨论】:

  • 因此,如果我使用 Post 而不是 Send,则不会产生错误。这只是关于我是否需要暂停线程池任务以发送/发布消息。对吗?
  • 我仍然对此感到困惑。我认为同步上下文为您提供了一种在 UI 线程上做一些工作的简单方法,所以您不必等待吗?或者它是这样工作的:你在后台线程上做一些工作,在中间你需要做一些 UI 工作,然后在后台线程中继续。如果您使用 Send 后台线程在 UI 工作完成之前不会继续到第 2 部分,但是如果您使用 Post 后台线程将继续工作而不等待 UI 线程工作?
  • 容易记住:你不等待Post,你只希望它会传递你的信息。
  • @TheMuffinMan 命名可能看起来很愚蠢或令人困惑,但这是因为它基于较低级别的抽象。大多数使用 SynchronizationContext 的人只关心同步或异步调用方法——按你说的做工作;但是,在稍低的级别上,这是通过消息和消息处理来处理的。在那个级别上,命名大多是有意义的,尽管 Send 和 SendAsync 可能会更好。也就是说,考虑到它的使用方式和时间,Invoke 和 InvokeAsync 可能更直接。
猜你喜欢
  • 1970-01-01
  • 2010-10-02
  • 2011-12-12
  • 2010-09-16
  • 2012-03-14
  • 2012-02-06
  • 2011-02-25
  • 2011-11-22
  • 2015-03-26
相关资源
最近更新 更多