我是否可以连续调用多个异步方法?

时间:2014-02-24 20:09:30

标签: c# asynchronous async-await

在启动期间,我需要获取两组数据的应用程序,每个数据都有其异步方法。如果我逐个调用它们,那么第二个调用只有在完成第一个调用后才会通过。

List<DataOne> DataCollectionOne;
List<DataTwo> DataCollectionTwo;

async void GetDatas()
    {
      if(sameCondOne)
        DataCollectionOne = await GetDataOne();
      if(sameCondTwo)
        DataCollectionTwo = await GetDataTwo();
    }

所以我将它们包装在任务调用中。

void GetDatas()
    {
      if(sameCondOne)
        Task.Run(() => RunDataOne());
      if(sameCondTwo)
        Task.Run(() => RunDataTwo());
    }

async void RunDataOne()
    {
      DataCollectionOne = await GetDataOne();
    }

async void RunDataTwo()
    {
      DataCollectionTwo = await GetDataTwo();
    }

我做得对吗?

2 个答案:

答案 0 :(得分:9)

没有。您不需要,也不想启动新线程只是为了负责启动这两个异步操作。只需启动这两个操作(调用方法就是启动操作的方法)并且在您启动它们之前不要等待:

var firstTask = GetDataOne();
var secondTask = GetDataTwo();

var firstResult = await firstTask;
var secondResult = await secondTask;

要处理条件检查,只需有条件地启动任务,然后有条件地分配结果:

Task<T> firstTask = null;
if(shouldGetFirstTask)
    firstTask = GetDataOne();
Task<T> secondTask = null;
if(shouldGetSecondTask)
    secondTask = GetDataTwo();

if(firstTask != null)
    DataCollectionOne = await firstTask;
if(secondTask != null)
    DataCollectionTwo = await secondTask;

答案 1 :(得分:3)

首先,你应该避免返回async方法(Best Practices in Asynchronous Programming)。

通常情况下,使用异步(或 TaskAsync ,如果已存在异步后缀方法)后缀async方法。

如果我理解正确,你想要产生一些条件异步相互依赖的任务,并等待所有任务结束而不让任何一个等待另一个任务。

由于你正在对编排方法中的任务结果做任何事情,但你需要一些副作用,我会将 Get~ 方法包装成运行〜像你这样的方法。

您可以在 Run〜方法中测试条件(通过显式测试条件或将其作为参数):

async Task RunDataOneAsymc()
{
    if (sameCondOne)
    {
        DataCollectionOne = await GetDataOneAsync();
    }
}

但如果条件为假,这仍然会产生不必要的任务。因此,最好将其保持在呼叫方:

async Task RunDataOneAsymc()
{
    DataCollectionOne = await GetDataOneAsync();
}

// ...
if (sameCondOne)
{
    await RunDataOneAsymc();
}

在编排方法中,如果条件为真,您将生成任务,然后等待所有任务完成:

async Task RunAll()
{
    var tasks = new List<Task>();

    if (sameCondOne)
    {
        await RunDataOneAsymc();
    }

    // ...

    if (sameCondN)
    {
        await RunDataNAsymc();
    }

    await Task.WhenAll(tasks);
}