任务链(等待上一个任务完成)

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

这是UI线程的运行。 我需要一个接一个地执行任务变量中的所有任务。 问题是如果我调用Task.WaitAll(任务),UI冻结。 如果没有UI冻结,我该如何做以下逻辑?

这不是任务链。

您需要使用ContinueWith进行任务链接。 上一个任务需要更新UI。

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

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

最好的方法是使用任务并行库(TPL)Continuations 。 延续不仅允许您创建任务流,还可以处理您的exception。 这是对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(() => 1) .ContinueWith(antTask => antTask.Result * 4) .ContinueWith(antTask => antTask.Result * 4) .ContinueWith(antTask =>Console.WriteLine(antTask.Result * 4)); // Prints 64. 

注意。 请务必在提供的第一个链接中阅读exception处理,因为这会导致TPL的新手误入歧途。

最后要特别注意你想要的是儿童任务。 子任务是创建为AttachedToParent任务。 在这种情况下,在所有子任务完成之前,延续不会运行

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

我希望这有帮助。

你需要使用Continorations:

 lastTask.ContinueWith(() => newTask.Start());