Подтвердить что ты не робот

В чем разница между SynchronizationContext.Send и SynchronizationContext.Post?

Благодаря Джереми Миллеру хорошая работа в Функциональное программирование для повседневной разработки .NET, у меня есть рабочий исполнитель команд, который делает все, что я хочу, чтобы он (делайте тяжелый подъем в пуле потоков, отправляйте результаты или ошибки обратно в контекст синхронизации и даже отправляйте ход обратно в контекст синхронизации), но я не могу объяснить, почему он использует SynchronizationContext.Send из пула потоков и Synchronization.Post из Func, переданного в метод, который делает тяжелый подъем. Я несколько раз читал документацию, но я просто не могу понять, в чем разница. Что я должен получить от того, что он называется Send, а один называется Post? Я чувствую, что магия заключается в том, что Send "запускает синхронный запрос" и Post "запускает асинхронный запрос", но оба запроса поступают из пула потоков и их необходимо отправить/отправить обратно в поток пользовательского интерфейса.

Может кто-нибудь объяснить разницу, даже если это всего лишь мнемоническое устройство, которое позволяет мне знать, когда выбрать один над другим?

В случае, если это имеет значение, это мой тестовый код, где я использую 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 для отправки сообщения завершения и ошибки обратно в пользовательский интерфейс:

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));
         }
     });
}
4b9b3361

Ответ 1

Отправить - синхронно: ждать ответа (или действие завершено)

Пост-асинхронный: отпасть и продолжить

Итак, ваш пример использует правильные методы в нужные моменты. Нет необходимости останавливать цикл for, пока обновление выполнения не будет завершено (наоборот).
И Execute хочет дождаться завершения действия, иначе обработка исключений не имеет никакой цели.