Преобразование модели асинхронного программирования (методы Begin / End) в асинхронную модель на основе событий? - PullRequest
1 голос
/ 09 ноября 2009

Допустим, у меня есть код, который использует модель асинхронного программирования, то есть он предоставляет следующие методы в качестве группы, которые могут использоваться синхронно или асинхронно:

public MethodResult Operation(<method params>);

public IAsyncResult BeginOperation(<method params>, AsyncCallback callback, object state);
public MethodResult EndOperation(IAsyncResult ar);

Я хочу обернуть этот код дополнительным слоем, который преобразует его в управляемую событиями асинхронную модель, например:

public void OperationAsync(<method params>);
public event OperationCompletedEventHandler OperationCompleted;
public delegate void OperationCompletedEventHandler(object sender, OperationCompletedEventArgs e);

Есть ли у кого-нибудь какое-либо руководство (или ссылки на такое руководство) о том, как этого добиться?

Ответы [ 2 ]

2 голосов
/ 15 января 2011

Вы можете использовать оболочку с помощью библиотеки AsyncFunc.

http://asyncfunc.codeplex.com

Код будет выглядеть так:

public class Original
{
    public ResultType Operation(ParamType param){...}
    public IAsyncResult BeginOperation(ParamType param, AsyncCallback callback, object state){...}
    public ResultType EndOperation(IAsyncResult ar){...}
}

public class Wrapper
{
    private AsyncFunc<ParamType, ResultType> _operation;
    private Original _original;

    public Wrapper(Original original)
    {
        _original = original;
        _operation = AsyncFunc<ParamType, ResultType>(_original.Operation);
    }

    public ResultType Operation(ParamType param)
    {
        return _original.Operation(param);
    }

    public void OperationAsync(ParamType param)
    {
        _operation.InvokeAsync(param)
    }

    public event AsyncFuncCompletedEventHandler<ResultType> OperationCompleted      
      {
        add { _operation.Completed += value; }
        remove { _operation.Completed -= value; }
    }
}

Обратите внимание, что в этом подходе вам не нужно определять пользовательский класс аргумента события и делегат обработчика события . Они могут быть заменены универсальными типами AsyncFunc:

OperationCompletedEventArgs -> ResultType
OperationCompletedEventHandler -> AsyncFuncCompletedEventHandler<ResultType>

Для более сложных сценариев перейдите на домашнюю страницу AsyncFunc. Есть несколько видео и образцов.

2 голосов
/ 09 ноября 2009

См. "Асинхронизация без боли" для некоторых мыслей по этому поводу; предоставленный код использует подход обратного вызова, но события будут достаточно простыми, если вы уроните его на экземпляр.

public static void RunAsync<T>(
    Func<AsyncCallback, object, IAsyncResult> begin,
    Func<IAsyncResult, T> end,
    Action<Func<T>> callback) {
    begin(ar => {
        T result;
        try {
            result = end(ar); // ensure end called
            callback(() => result);
        } catch (Exception ex) {
            callback(() => { throw ex; });
        }
    }, null);
}
...