Question

I always thought I could use SynchronizationContext to marshal a call to another thread. Apparently I was wrong as SyncCtx.Send() doesn't do anything but invoking the given delegate (stays on the same thread). Do I really need to derive from SynchronizationContext and do work on the thread context? I feel like missing something.

What I want to achive: Imagine a little API for executing commands within an app. You can also execute a command on a background thread, as you can assign a delegate to run when the command has finished execution. This "Call-me-when-done"-Delegate gets one single paramter (State) containing success/failure flag, optional exception information, etc. I want to call this delegate on the original calling thread so that devs using the lib do not need to handle invoke required etc. I would just like to take this away and let them do simple non-thread-aware programming. WindowsFormsSynchronizationContext doesn't seem to help either if you don't give it some control as a target.

Thanks for any help!

Was it helpful?

Solution

When you are in winforms and you use the synchronizationcontext the call will be marshalled to the GUI thread.

for your specific case I guess something like this should work, probably it will be a good idea to create a class that represents a Command

public class CommandManager
{
    private readonly SynchronizationContex _synchronizationContex;

    public CommandManager(SynchronizationContext synchronizationContex)
    {
        _synchronizationContex = synchronizationContex;
    }

    public void ExecuteAsync(Func<State> action, Action<State> callback)
    {
        ThreadPool.QueueUserWorkItem(o => {
                                             state = action();
                                             _synchronizationContex.Send(oo => callback(state));
                                          });
    } 
}

you'd create like this (in the GUI thread, so for example in your main form)

var commandManager = new CommandManager(SynchronizationContext.Current);

you'd use it like this:

commandManager.ExecuteAsync(() => new State() { Success = true }, 
                             c => MessageBox.Show("success in the GUI thread"));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top