Благодаря хорошей работе Джереми Миллера в Функциональное программирование для повседневной разработки .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));
}
});
}