Каркас, как нить маршаллинг - PullRequest
1 голос
/ 19 декабря 2011

Я всегда думал, что смогу использовать SynchronizationContext для перенаправления вызова в другой поток.Очевидно, я был неправ, так как SyncCtx.Send () ничего не делает, кроме вызова данного делегата (остается в том же потоке).Мне действительно нужно извлечь из SynchronizationContext и работать с контекстом потока?Я чувствую, что чего-то не хватает.

Чего я хочу достичь: представьте себе небольшой API для выполнения команд в приложении.Вы также можете выполнить команду в фоновом потоке, так как вы можете назначить делегата для запуска, когда команда завершит выполнение.Этот "Call-me-when-done" -Delegate получает один единственный параметр (State), содержащий флаг успеха / неудачи, необязательную информацию об исключениях и т. Д. Я хочу вызвать этот делегат в исходном вызывающем потоке, чтобы разработчики, использующие lib, не делали этого.необходимо обработать требуемый вызов и т. д. Я просто хотел бы убрать это и позволить им выполнять простое программирование без учета потоков.WindowsFormsSynchronizationContext, похоже, тоже не поможет, если вы не предоставите ему некоторый контроль в качестве цели.

Спасибо за любую помощь!

1 Ответ

0 голосов
/ 19 декабря 2011

Когда вы используете winforms и используете синхронизирующий текст, вызов будет перенаправлен в поток GUI.

для вашего конкретного случая, я думаю, что-то вроде этого должно сработать, возможно, будет хорошей идеей создать класс, представляющий 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));
                                          });
    } 
}

, который вы создадите следующим образом.(в потоке GUI, например, в основной форме)

var commandManager = new CommandManager(SynchronizationContext.Current);

вы бы использовали его так:

commandManager.ExecuteAsync(() => new State() { Success = true }, 
                             c => MessageBox.Show("success in the GUI thread"));
...