cor*_*rax 4 c# asynchronous task-parallel-library .net-4.5
我想在异步任务成功完成时运行一些代码.
从阅读网络上的文档和示例,我想我可以使用Task.ContinueWith和指定TaskContinuationOptions.OnlyOnRanToCompletion.
但是,这并不像我预期的那样.
以下代码是在Visual Studio 2012中创建的控制台程序.Net 4.5:
using System;
using System.Threading.Tasks;
namespace TaskContinueTest
{
class Program
{
static void Main(string[] args)
{
var jobTask = Task.Factory.StartNew(() => { });
jobTask.ContinueWith((task, options) =>
{
Console.WriteLine("Completed handler. Task status is {0}", task.Status);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
jobTask.ContinueWith((task, options) =>
{
Console.WriteLine("Faulted handler. Task status is {0}", task.Status);
}, TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行时,我得到输出:
Completed handler. Task status is RanToCompletion
Faulted handler. Task status is RanToCompletion
Run Code Online (Sandbox Code Playgroud)
这是非常令人惊讶的(至少对我而言).为什么两个延期都安排好了?
如果我抛出异常,我会得到相同的行为jobTask,但输出现在是:
Completed handler. Task status is Faulted
Faulted handler. Task status is Faulted
Run Code Online (Sandbox Code Playgroud)
所以框架清楚地知道任务的状态,但为什么两个延续仍然安排?
我认为问题是你不小心打电话给这个超载
public Task ContinueWith(
Action<Task, Object> continuationAction,
Object state
)
Run Code Online (Sandbox Code Playgroud)
你想要的是这个重载:
public Task ContinueWith(
Action<Task> continuationAction,
TaskContinuationOptions continuationOptions
)
Run Code Online (Sandbox Code Playgroud)
您只需要更改lambda表达式以使用单个参数:
Task.ContinueWith(task => Console.WriteLine(...),
TaskContinuationOptions.OnlyOnRanToCompletion);
Run Code Online (Sandbox Code Playgroud)