fra*_*fra 6 c# workflow-foundation-4 async-await
很长一段时间我使用以下模板编写自定义AsyncCodeActivity类:
public sealed class MyActivity : AsyncCodeActivity<T>
{
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
var task = new Task<T>(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<T>;
if (task.Exception != null)
{
// Error handling. Rethrow? Cancel?
}
return task.Result;
}
private T Execute(object state)
{
// Logic here
return default(T);
}
}
Run Code Online (Sandbox Code Playgroud)
我有一些问题:
谢谢
Ste*_*ary 14
1)您应该从您的EndExecute方法中重新抛出异常.
2)我建议你创建自己的基本类型.我在AsyncTaskCodeActivity<T>下面写了一个:
public abstract class AsyncTaskCodeActivity<T> : AsyncCodeActivity<T>
{
protected sealed override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
var task = ExecuteAsync(context);
var tcs = new TaskCompletionSource<T>(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<T>)result;
try
{
return task.Result;
}
catch (AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
throw;
}
}
protected abstract Task<T> ExecuteAsync(AsyncCodeActivityContext context);
}
Run Code Online (Sandbox Code Playgroud)
如果您使用我的AsyncEx库,这个包装器变得更加简单:
public abstract class AsyncTaskCodeActivity<T> : AsyncCodeActivity<T>
{
protected sealed override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
var task = ExecuteAsync(context);
return AsyncFactory<T>.ToBegin(task, callback, state);
}
protected sealed override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
return AsyncFactory<T>.ToEnd(result);
}
protected abstract Task<T> ExecuteAsync(AsyncCodeActivityContext context);
}
Run Code Online (Sandbox Code Playgroud)
获得基本类型后,您可以定义自己的派生类型.这是一个使用async/ await:
public sealed class MyActivity : AsyncTaskCodeActivity<int>
{
protected override async Task<int> ExecuteAsync(AsyncCodeActivityContext context)
{
await Task.Delay(100);
return 13;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个将CPU绑定工作安排到线程池(类似于您当前的模板):
public sealed class MyCpuActivity : AsyncTaskCodeActivity<int>
{
protected override Task<int> ExecuteAsync(AsyncCodeActivityContext context)
{
return Task.Run(() => 13);
}
}
Run Code Online (Sandbox Code Playgroud)
来自评论的更新:这是使用取消的.我不是100%肯定它是正确的,因为取消本身是异步的,并且语义AsyncCodeActivity<T>.Cancel是未被记录的(即,Cancel应该等待活动在取消状态下完成?活动是否可以接受成功完成后Cancel是叫什么名字?).
public abstract class AsyncTaskCodeActivity<T> : AsyncCodeActivity<T>
{
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<T>.ToBegin(task, callback, state);
}
protected sealed override T EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
try
{
return AsyncFactory<T>.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<T> ExecuteAsync(AsyncCodeActivityContext context, CancellationToken cancellationToken);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4909 次 |
| 最近记录: |