任务链接(等待前一个任务完成)

20
var tasks = new List<Task>();

foreach (var guid in guids)
{
    var task = new Task( ...);
    tasks.Add(task);
}

foreach (var task in tasks)
{
    task.Start();
    Task.WaitAll(task);
}

这是UI线程的运行。我需要依次执行tasks变量中的所有任务。问题在于,如果我调用Task.WaitAll(task),UI会冻结。如何在不冻结UI的情况下实现以下逻辑?


4
那你为什么不直接创建一个大的代表团呢? - SLaks
补充一下@SLaks所说的,如果你只是有一些要运行的列表,使用类似BackgroundWorker的东西可能会更简单。真正的未知因素是当后台工作完成时,你想要发生什么 - 假设它是某种UI更新,BackgroundWorker已经通过在UI线程上运行完成的委托来处理了这个问题。 - James Manning
3个回答

33

这不是任务链。

你需要使用ContinueWith来进行任务链。最后一个任务需要更新UI。

Task.Factory.StartNew( () => DoThis())
   .ContinueWith((t1) => DoThat())
   .ContinueWith((t2) => UpdateUi(), 
       TaskScheduler.FromCurrentSynchronizationContext());

注意:最后一行使用了TaskScheduler.FromCurrentSynchronizationContext(),这将确保任务在同步上下文(UI线程)中运行。


16

最好的方法是使用任务并行库(TPL)继续。Continuation 不仅允许您创建任务流,还可以处理异常。这是TPL的很好的入门介绍。但为了给你一些概念...

您可以使用下面的方式开始一个TPL任务:

Task task = Task.Factory.StartNew(() => 
{
    // Do some work here...
});

现在,要在原任务完成时(无论是成功还是错误)启动第二个任务,您可以使用ContinueWith方法。

Task task1 = Task.Factory.StartNew(() => Console.WriteLine("Antecedant Task"));
Task task2 = task1.ContinueWith(antTask => Console.WriteLine("Continuation..."));

task1完成、失败或被取消时,task2就会启动并开始运行。请注意,如果task1在第二行代码之前已完成,则task2将立即被调度执行。传递给第二个lambda表达式的antTask参数是对先行任务的引用。有关更详细的示例,请参见此链接...

您还可以从先行任务中传递连续结果。

Task.Factory.StartNew<int>(() => 1)
    .ContinueWith(antTask => antTask.Result * 4)
    .ContinueWith(antTask => antTask.Result * 4)
    .ContinueWith(antTask =>Console.WriteLine(antTask.Result * 4)); // Prints 64.

注意:务必阅读第一个链接中关于异常处理的内容,因为这可能会让新手误入TPL。

特别需要注意的是,如果要实现您所需的功能,请查看子任务。子任务是通过 AttachedToParent 创建的任务。在这种情况下,延续将不会运行,直到所有子任务都已完成。

TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
Task.Factory.StartNew(() =>
{
    Task.Factory.StartNew(() => { SomeMethod() }, atp);
    Task.Factory.StartNew(() => { SomeOtherMethod() }, atp); 
}).ContinueWith( cont => { Console.WriteLine("Finished!") });

希望这能帮到你。


5
您需要使用“continuations”(续体):
lastTask.ContinueWith(() => newTask.Start());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接