启动异步操作,然后等待

时间:2013-09-21 21:15:20

标签: c# asynchronous async-await

我现在才开始玩异步和等待。我有8个单独的数据库调用,有些依赖于其他调用。我希望能够启动3个异步方法,然后当某个1返回时,启动3个其他方法,然后当某个1返回时,再启动2个。我目前正在使用3个Parallel.Invoke方法来完成此任务,但每个并行必须等到所有方法返回。我只关心 1方法返回,其他人可以在后台运行,直到最后await Task.WhenAll(t1,t2,t3,...,t6)有没有办法用async / await关闭它?

我知道await不是阻塞,但是它停止执行我的main方法(带有8个db调用),直到从方法返回值(就像同步方法一样)。

2 个答案:

答案 0 :(得分:5)

您可以使用Task.WhenAny等待以下任何一项任务:

var completedTask = await Task.WhenAny(t1, t2, t3, ...);

如果你有一个更复杂的依赖结构,那么我建议用async方法表示:

static async Task DoMasterOperationAsync()
{
  var result = await StartSomething();
  await Task.WhenAll(DoComplexOperationAsync(), result.NextT1Async());
}

static async Task DoComplexOperationAsync()
{
  var result1 = await T1Async();
  await Task.WhenAll(result1.NextT1Async(), result1.NextT2Async(), result1.NextT3Async());
}

await Task.WhenAll(DoMasterOperationAsync(), t2, t3, ...);

答案 1 :(得分:0)

我的问题是我不知道Task.Run允许你开始任务,然后等待它。我在another answer中通过@StephenCleary找到了这个。谢谢斯蒂芬,你在那里得到了我的支持!这是我完全做作的例子,它完成了我上面要做的事情:

        Func<Task<int>> t1 = async () => { await Task.Delay(4000); return 1; };
        Func<Task<int>> t2 = async () => { await Task.Delay(5000); return 2; };
        Func<int, Task<int>> t3 = async (val) => { await Task.Delay(3000); return 3; };
        Func<int, Task<int>> t4 = async (val) => { await Task.Delay(4000); return 4; };
        Func<int, Task<int>> t5 = async (val) => { await Task.Delay(3000); return 5; };
        Func<int, Task<int>> t6 = async (val) => { await Task.Delay(2000); return 6; };
        Func<int, Task<int>> tSecondary = async (val) => { await Task.Delay(3000); return 7; };
        Func<Task<int>> tPrimary = async () => { await Task.Delay(2000); return 8; };
        //kick off first 3 calls
        var primaryR = Task.Run(tPrimary);
        var t1R = Task.Run(t1);
        var t2R = Task.Run(t2);
        //await 1 of the 3
        var primary = await primaryR;
        //start 2 of 3 dependent tasks
        var t3R = Task.Run(() => t3(primary));
        var t4R = Task.Run(() => t4(primary));
        //kick off and await secondaryMasterTaskAsync
        var secondary = await tSecondary(primary);
        //start final 2
        var t5R = Task.Run(() => t5(secondary));
        var t6R = Task.Run(() => t6(secondary));
        //await all tasks that haven't been awaited previously
        var tasks = await Task.WhenAll(t1R, t2R, t3R, t4R, t5R, t6R);