31

感谢 Jeremy Miller 在为日常 .NET 开发的函数式编程方面所做的出色工作,我有一个工作命令执行器,它可以执行我想做的所有事情(在线程池上进行繁重的工作,将结果或错误发送回同步上下文,甚至发布回到同步上下文),但我无法解释为什么它使用来自线程池的SynchronizationContext.Send和从传递到执行繁重工作的方法中的Synchronization.Post 。Func我已多次阅读文档,但我无法直观地了解其中的区别。我应该从一个被调用Send和一个被调用的事实中得到Post什么?我觉得魔法就在事实中Send“启动同步请求”和Post“启动异步请求”,但两个请求都来自线程池,需要发送/回传到 UI 线程。

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

万一这很重要,这是我用来将进度发送回 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));
         }
     });
}
4

1 回答 1

36

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

后异步:下车并继续

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).
And Execute does want to wait for the Action to complete, otherwise the exception handling has no purpose.

于 2010-03-18T20:34:15.327 回答