我有这两种情况,但我不明白为什么会发生这样的事情:
static void Main(string[] args)
{
Console.WriteLine("***Starting T1");
//run two tasks sequentially
Task t = FirstTask().ContinueWith(_ => SecondTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
//register succeded and faulted continuations
t.ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t.ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();
Console.WriteLine("***Starting T2");
Task t2 = FirstTask().ContinueWith(_ => FaultTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
t2.ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t2.ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();
Console.WriteLine("***Starting T3");
Task t3 = FirstTask().ContinueWith(ant => ant.ContinueWith(_ => FaultTask(), TaskContinuationOptions.OnlyOnRanToCompletion));
t3.ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t3.ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();
}
private static Task FirstTask()
{
return Task.Run(() =>
{
Console.WriteLine("Task 1");
Thread.Sleep(1000);
});
}
private static Task SecondTask()
{
return Task.Run(() =>
{
Console.WriteLine("Task 2");
Thread.Sleep(1000);
});
}
private static Task FaultTask()
{
return Task.Run(() =>
{
Console.WriteLine("Throw...");
Thread.Sleep(1000);
throw new ArgumentException();
});
}
private static void Completion()
{
Console.WriteLine("Complete");
}
private static void Faulted()
{
Console.WriteLine("Faulted");
}
在案例1中,事情按预期运行。但是,如果Sleep()
中的FirstTask()
被删除,则无法保证任务按顺序运行。
在案例2中,Faulted()
处理程序未运行。我希望这会发生,因为有一个未处理的异常。
在第3种情况下,运行Complete()
处理程序后抛出异常。我很困惑为什么会发生这种排序。
基本上我希望能够根据我的需要链接任意数量的任务,并让它们在上一个完成之后按顺序运行。创建链后,我将显示一个等待表单并将OnlyOnRanToCompletion
,OnlyOnCancelled
,OnlyOnFaulted
的延续注册到最终任务中(读取:毕竟已完成)以关闭表格 - 显示成功或错误。
这是MSDN所指的那些不可用于多任务延续的选项吗?
答案 0 :(得分:2)
t
和t2
上的归档类型Task<Task>
不仅仅是一项任务。 T3是Task<Task<Task>>
。要获得所需的行为,您应该Unwrap能够为您提供代表整个操作的任务的任务(阅读文档以获取更多信息):
Console.WriteLine("***Starting T1");
//run two tasks sequentially
Task<Task> t = FirstTask().ContinueWith(_ => SecondTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
//register succeded and faulted continuations
t.Unwrap().ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t.Unwrap().ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();
Console.WriteLine("***Starting T2");
Task<Task> t2 = FirstTask().ContinueWith(_ => FaultTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
t2.Unwrap().ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t2.Unwrap().ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();
我建议尽可能使用async / await模式,因为这样可以更轻松地处理这些任务。