如何处理来自多个线程的单个结果?

时间:2017-11-12 12:48:44

标签: c# .net task-parallel-library

假设我的文件格式很少,我可以阅读。例如。 xml,yaml和json。 对于每种格式我都有特定的读者,但我不知道直到运行时放置了哪个文件,所以我尝试用所有这些读者阅读文件。 整个过程目前是异步的。

我想要的只是一种正确的方法,只返回带有结果的'FileReaderTask'。

到目前为止,我带来了这个,但我不太喜欢它。 特别是我返回null的部分

    public async Task<ReadResponse> Read(string id)
{
  var readerDetails = _readerDetailsRepository.GetAll();
  var tasks = readerDetails.Select(readerDetail => _reader.ReadAsync(readerDetail, id)).ToList();

  foreach (var result in await Task.WhenAll(tasks))
  {
    if (!string.IsNullOrEmpty(result)) // only one will have the response !
    {
      return await HandleResponse(_jsonConverter.Convert<ReadResponse>(result), id);
    }
  }
  return null; // ?? seems pretty bad
}

1 个答案:

答案 0 :(得分:3)

你的进程是异步的,但它没有使用多个线程。在这种情况下,这是一件好事,因为读取同一文件的线程将相互竞争。

您当前的方法使用WhenAll,它会在选择结果之前等待所有任务完成。这很好,假设所有失败的任务首先完成。您不必等待所有任务,而是在完成任务时对其进行处理:

var tasks = readerDetails.Select(readerDetail =>
    _reader.ReadAsync(readerDetail, id).ConfigureAwait(false)
).ToList();
foreach (var task in tasks) {
    var result = await task;
    if (!string.IsNullOrEmpty(result)) {
        return await HandleResponse(_jsonConverter.Convert<ReadResponse>(result), id);
    }
}

循环一个接一个地等待各个任务,因此如果成功的任务在不成功的任务之前完成,则在处理响应之前,您的代码不会等待剩余任务的完成。