Thanks to Jeremy Miller's good work in Functional Programming For Everyday .NET Development, I have a working command executor that does everything I want it to (do heavy lifting on the thread pool, send results or errors back to the synchronization context, and even post progress back to the synchronization context), but I can't explain why it uses SynchronizationContext.Send from the thread-pool and Synchronization.Post from the Func passed into the method that does the heavy lifting. I have read the documentation, several times, but I just can't get a gut sense for what the difference is. What am I supposed to get from the fact that one is called Send and one is called Post? I sense the magic is in the fact Send "starts a synchronous request" and Post "starts an asynchronous request", but both requests come from the thread pool and need to be sent/posted back to the UI thread.
Can someone explain the difference, even if it is just a mnemonic device that lets me know when to choose one over the other?
In case it matters, this is my test code where I use Post to send progress back to the 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);
}
That _ExecuteCommand method is passed in as the command parameter below, mostly from the original article, that uses Send to send completion and error message back to the 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));
         }
     });
}
 
     
    