Let's say I have code that uses the Asynchronous Programming Model, i.e. it provides the following methods as a group which can be used synchronously or asynchronously:
public MethodResult Operation(<method params>);
public IAsyncResult BeginOperation(<method params>, AsyncCallback callback, object state);
public MethodResult EndOperation(IAsyncResult ar);
What I want to do is wrap this code with an additional layer that will transform it into the event-driven asynchronous model, like so:
public void OperationAsync(<method params>);
p开发者_运维技巧ublic event OperationCompletedEventHandler OperationCompleted;
public delegate void OperationCompletedEventHandler(object sender, OperationCompletedEventArgs e);
Does anyone have any guidance (or links to such guidance) on how to accomplish this?
See "Async without the pain" for some thoughts on this; the code supplied uses a callback approach, but events would be easy enough if you drop it on an instance.
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);
}
You can the wrapper using AsyncFunc library.
http://asyncfunc.codeplex.com
The code would look like this:
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; }
}
}
Notice that in this approach you don't need to define custom event argument class and event handler delegate. They can be substituted with AsyncFunc generic types:
OperationCompletedEventArgs -> ResultType
OperationCompletedEventHandler -> AsyncFuncCompletedEventHandler<ResultType>
For more advanced scenarios go to AsyncFunc home page. There are some videos and samples.
精彩评论