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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11649628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 18:40:01  来源:igfitidea点击:

Task chaining (wait for the previous task to completed)

c#.nettask-parallel-librarytask

提问by Melursus

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);
}

This is run of the UI thread. I need to execute all tasks in tasks variable one after the other. The problem is if I call Task.WaitAll(task), the UI freeze. How can I do the following logic without having the UI freeze?

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

采纳答案by Aliostad

This is not Task Chaining.

这不是任务链。

You need to do Task chaining using ContinueWith. Last task would need to update the UI.

您需要使用ContinueWith. 最后一个任务需要更新 UI。

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

Notethe last line has TaskScheduler.FromCurrentSynchronizationContext()this will ensure task will run in the synchronization context (UI Thread).

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

回答by SLaks

You need to use continutations:

您需要使用延续:

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

回答by MoonKnight

The best way is to use the Task Parallel Library (TPL)and Continuations. A continuation not only allows you to create a flow of tasks but also handles your exceptions. This is a great introductionto the TPL. But to give you some idea...

最好的方法是使用Task Parallel Library (TPL)Continuations。延续不仅允许您创建任务流,还可以处理您的异常。这是对 TPL 的一个很好的介绍。但是为了给你一些想法......

You can start a TPL task using

您可以使用以下命令启动 TPL 任务

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

Now to start a second task when an antecedent task finishes (in error or successfully) you can use the ContinueWithmethod

现在要在先行任务完成(错误或成功)时开始第二个任务,您可以使用该ContinueWith方法

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

So as soon as task1completes, fails or is cancelled task2'fires-up' and starts running. Note that if task1had completed before reaching the second line of code task2would be scheduled to execute immediately. The antTaskargument passed to the second lambda is a reference to the antecedent task. See this linkfor more detailed examples...

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

You can also pass continuations results from the antecedent task

您还可以传递来自先行任务的延续结果

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

Note. Be sure to read up on exception handling in the first link provided as this can lead a newcomer to TPL astray.

笔记。请务必阅读提供的第一个链接中的异常处理,因为这可能会使新手误入 TPL。

One last thing to look at in particular for what you want is child tasks. Child tasks are those which are created as AttachedToParent. In this case the continuation will not run until all child tasks have completed

要特别注意您想要的最后一件事是子任务。子任务是那些创建为AttachedToParent. 在这种情况下,在所有子任务完成之前,continuation 不会运行

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

I hope this helps.

我希望这有帮助。