10

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

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

4

2 回答 2

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, ...);
于 2013-09-21T21:19:40.537 回答
0

我的问题是我不知道Task.Run这可以让你开始一项任务,然后等待它。我在@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);
于 2013-09-22T02:19:39.203 回答