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