实现AsyncCodeActivities(使用C#async / await)

很长一段时间我使用以下模板编写自定义AsyncCodeActivity类:

public sealed class MyActivity : AsyncCodeActivity { protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state) { var task = new Task(this.Execute, state, CancellationToken.None, TaskCreationOptions.AttachedToParent); task.ContinueWith(s => callback(s)); task.Start(); return task; } protected override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result) { var task = result as Task; if (task.Exception != null) { // Error handling. Rethrow? Cancel? } return task.Result; } private T Execute(object state) { // Logic here return default(T); } } 

我有一些问题:

  1. 哪种方法可以处理exception? 重新抛出? 将上下文设置为已取消?
  2. 是否有一种优雅的方式来编写现在可用的async / await语法?

谢谢

1)您应该从EndExecute方法重新抛出exception。

2)我建议你创建自己的基本类型。 我在下面写了一个名为AsyncTaskCodeActivity

 public abstract class AsyncTaskCodeActivity : AsyncCodeActivity { protected sealed override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state) { var task = ExecuteAsync(context); var tcs = new TaskCompletionSource(state); task.ContinueWith(t => { if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions); else if (t.IsCanceled) tcs.TrySetCanceled(); else tcs.TrySetResult(t.Result); if (callback != null) callback(tcs.Task); }); return tcs.Task; } protected sealed override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result) { var task = (Task)result; try { return task.Result; } catch (AggregateException ex) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); throw; } } protected abstract Task ExecuteAsync(AsyncCodeActivityContext context); } 

如果您使用我的AsyncEx库,这个包装器变得更加简单:

 public abstract class AsyncTaskCodeActivity : AsyncCodeActivity { protected sealed override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state) { var task = ExecuteAsync(context); return AsyncFactory.ToBegin(task, callback, state); } protected sealed override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result) { return AsyncFactory.ToEnd(result); } protected abstract Task ExecuteAsync(AsyncCodeActivityContext context); } 

获得基本类型后,您可以定义自己的派生类型。 这是一个使用async / await

 public sealed class MyActivity : AsyncTaskCodeActivity { protected override async Task ExecuteAsync(AsyncCodeActivityContext context) { await Task.Delay(100); return 13; } } 

这是一个将CPU绑定工作安排到线程池(类似于您当前的模板):

 public sealed class MyCpuActivity : AsyncTaskCodeActivity { protected override Task ExecuteAsync(AsyncCodeActivityContext context) { return Task.Run(() => 13); } } 

来自评论的更新:这是使用取消的。 我不是100%确定它是正确的,因为取消本身是异步的,并且AsyncCodeActivity.Cancel的语义AsyncCodeActivity.Cancel记录(即, Cancel是否应该等待活动在取消状态下完成?是否可以接受?在调用Cancel后成功完成的活动?)。

 public abstract class AsyncTaskCodeActivity : AsyncCodeActivity { protected sealed override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state) { var cts = new CancellationTokenSource(); context.UserState = cts; var task = ExecuteAsync(context, cts.Token); return AsyncFactory.ToBegin(task, callback, state); } protected sealed override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result) { try { return AsyncFactory.ToEnd(result); } catch (OperationCanceledException) { if (context.IsCancellationRequested) context.MarkCanceled(); else throw; return default(T); // or throw? } } protected override void Cancel(AsyncCodeActivityContext context) { var cts = (CancellationTokenSource)context.UserState; cts.Cancel(); } protected abstract Task ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken); }