等待任务列表而不阻止其他任务列表

时间:2017-11-02 20:46:32

标签: c# .net async-await task latency

我正在处理一段代码,该代码从一个源获取数据,进行一些处理,然后将其保存到不同的源。由于两端的延迟都很高,我试图使用async / await来等待加载和保存操作完成。理想情况下,这将启动所有输入任务,当每个任务完成时,它会执行一些快速处理,然后启动输出任务 - 使用Task.WaitAll会导致程序在新任务可能启动时无效。

由于第二个异步任务取决于第一个异步任务的结果,我无法弄清楚如何处理第二个异步等待,以便让它从第一个await恢复处理其他结果 - 一旦结果是处理完第二次await后,它会完全阻塞,直到完成保存功能,而不是恢复处理其他结果。我尝试这样的事情,我做错了什么?

async Task MainAsync()
{
    /* gets a list of id's */

    var dataRequests = ids.Select(id => LoadEntryById(id)).ToList();

    foreach(var request in dataRequests)
    {
        RawEntry response = await request;

        ProcessedEntry result = doSomething(response);

        await SaveResult(result);
    }
}

async Task<RawEntry> LoadEntryById(int id)
{
    /* IO task */
}

async Task SaveResult(ProcessedEntry result)
{
    /* IO task */
}

2 个答案:

答案 0 :(得分:3)

不是等待单一方法,而是使用续集创建List<Task>,然后使用Task.WhenAll

var tasks = ids.Select(async id => {
    var response = await LoadEntryById(id);
    var result = doSomething(response);
    await SaveResult(result);
}).ToList();

await Task.WhenAll(tasks);

这将以异步方式处理您的所有任务。

答案 1 :(得分:-1)

如果我理解正确,你可以试试这个:

Parallel.Foreach( ids.Select(id => LoadEntryById(id)), (rawEntry) => {
    var result = doSomething(rawEntry);

    await SaveResult(result);
}

RawEntry LoadEntryById(int id)
{
    /* IO task */
}

async Task SaveResult(ProcessedEntry result)
{
    /* IO task */
}

在此设置中LoadEntryById不需要返回任务,但这取决于它正在做什么。