我正在设计一个API,公开一个可取消的Task
,并且想确保我已经正确地设计了它。是否有暴露Task
s的标准模式(可能类似于APM BeginXxx/EndXxx模式)?任何改善建议?请参阅MyAPI.Run
公开一个可取消的任务
是否Test2
演示了并行运行多个MyAPI.Run
任务的最佳方式?
public static class MyAPI
{
public static Task<MyResult> Run(CancellationToken token) {
// lazily create Task, so as to include the specified CancellationToken
return new Task<MyResult>(MyPrivateAsyncMethod, token, token);
}
private static MyResult MyPrivateAsyncMethod(object state) {
CancellationToken ct = (CancellationToken)state;
ct.ThrowIfCancellationRequested();
return new MyResult();
}
}
public static class TestMyAPI
{
// User can start the Task directly
public static void Test1() {
CancellationTokenSource cts = new CancellationTokenSource();
MyAPI.Run(cts.Token)
.ContinueWith(task => Console.WriteLine(task.Result.ToString()))
.Start();
}
// User must wrap in new Tasks to get Parent/Child relationship
public static void Test2() {
CancellationTokenSource cts = new CancellationTokenSource();
Task.Factory.StartNew(() =>
{
var childTasks = new[] {
Task.Factory.StartNew<MyResult>(() => MyAPI.Run(cts.Token).Result, cts.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default),
Task.Factory.StartNew<MyResult>(() => MyAPI.Run(cts.Token).Result, cts.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default)
};
Task.Factory
.ContinueWhenAll<MyResult>(childTasks, tasks => { foreach(var task in tasks) task.ToString(); })
.Start();
}, cts.Token);
}
}
关于你的Test2重写,会发生什么异常处理?具体来说,通过父母/孩子的安排,我会'尝试'父母并且抓住子女抛出的任何东西的'AggergateException'。这将如何工作在你的重写? – nmarler
@nmarler你必须在继续处理它 - 你可以明确地将一个Try/catch包围在一个调用中,以便继续处理错误,如果需要的话。 –
我正在考虑只返回'热'任务的概念。在我的应用程序中,我有一个“SequenceManager”对象,负责运行其他类中的一些任务。当SequenceManager被初始化时,我的意图是以某种安排(某些顺序相互连接,某些异步)组成任务子对象任务。然后,在将来的某个时刻,可以运行这个“主”任务。我认为现在应该简化SequenceManager init,而是暴露一个RunAsync方法,它将即时组成子RunAsyncs。谢谢,你的建议是非常有帮助的 – nmarler