Pregunta

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!

¿Fue útil?

Solución

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"));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top