在不同时间需要返回值时,将任务链接在一起的正确方法 [英] Correct way to link Tasks together when return values are needed at different times

查看:218
本文介绍了在不同时间需要返回值时,将任务链接在一起的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望这有意义 - 假设我有以下代码:

  Task.Run(()=> 
{
return Task.WhenAll

Task1,
Task2,
...
Taskn

。继续(tsks =>
{
TaskA(使用任务Task1和Task2的输出)
}
,ct)
。 >
{
TaskB(使用TaskA和Task3的输出)
}
,ct);
}

所以我想让所有我的前N个任务并发运行(因为我们没有相互依赖)一旦他们都完成了,继续一个任务,依赖于他们的输出(我得到这个,我可以使用 tsks.Result )。
但是我想继续执行一个任务,该任务依赖于第一个任务和 TaskA 的结果。



我有点失去了如何正确地构建我的代码,所以我可以访问我的第一组任务的结果,除了立即执行 ContinueWith 。 / p>

我的一个想法是在我的方法中为它们分配返回值 - 类似:

 code> ...声明任务外的变量... 

Task.Run(()=>
{
return Task.WhenAll

Task.Run(()=> {var1 = Task1.Result;},ct),
...
Task.Run(()=> {varn = Taskn .Result;},ct),

.ContinueWith(tsks =>
{
TaskA(使用Tasks var1& varn的输出)
}
,ct)
.ContinueWith(res =>
{
TaskB(使用TaskA和var3的输出)
}
,ct );
});

但是,即使这对我有用,但我毫无疑问这是错误的。



什么是正确的方法?我应该有一个状态对象包含所有必要的变量,并通过我的所有任务?是否有更好的方法?



请原谅我的无知在这里 - 我只是非常新的并发编程。

Task1 Task2 ,..., code> TaskN 在 WhenAll 的调用范围内,因为在时间 ContinueWith 传递控制到你的下一个任务所有的早期任务都保证完成,可以安全地使用 TaskX.Result 在代码实现连续:

  .ContinueWith(tsks => 
{
var resTask1 = Task1.Result;
...
}
,ct)

,因为任务 Task1 已完成运行。


I hope this makes sense - Suppose I have the following code:

Task.Run(() =>
{
    return Task.WhenAll
        (
            Task1,
            Task2,
            ...
            Taskn
        )
        .ContinueWith(tsks=>
            {
                TaskA (uses output from Tasks Task1 & Task2, say)
            }
        , ct)
        .ContinueWith(res =>
            {
                TaskB (uses output from TaskA and Task3, say)
            }
        , ct);
});

So I want all my first N tasks to run concurrently (since we have no interdependencies), then only once they're all finished, to continue with a task that relies on their outputs (I get that for this, I can use the tsks.Result). BUT THEN I want to continue with a task that relies on one of the first tasks and the result of TaskA.

I'm a bit lost how to structure my code correctly so I can access the results of my first set of tasks outside of the immediately proceeding ContinueWith.

My one thought was to assign return value to them within my method - Something like:

... declare variables outside of Tasks ...

Task.Run(() =>
{
    return Task.WhenAll
        (
            Task.Run(() => { var1 = Task1.Result; }, ct),
            ...
            Task.Run(() => { varn = Taskn.Result; }, ct),
        )
        .ContinueWith(tsks=>
            {
                TaskA (uses output from Tasks var1 & varn, say)
            }
        , ct)
        .ContinueWith(res =>
            {
                TaskB (uses output from TaskA and var3, say)
            }
        , ct);
});

But, even though this works for me, I have no doubt that that is doing it wrong.

What is the correct way? Should I have a state object that contains all the necessary variables and pass that throughout all my tasks? Is there a better way in total?

Please forgive my ignorance here - I'm just VERY new to concurrency programming.

解决方案

Since Task1, Task2, ... , TaskN are in scope for the call of WhenAll, and because by the time ContinueWith passes control to your next task all the earlier tasks are guaranteed to finish, it is safe to use TaskX.Result inside the code implementing continuations:

.ContinueWith(tsks=>
        {
            var resTask1 = Task1.Result;
            ...
        }
    , ct)

You are guaranteed to get the result without blocking, because the task Task1 has finished running.

这篇关于在不同时间需要返回值时,将任务链接在一起的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆