C#异步方法基于第一个完成的任务执行

C# async method execute base on the first completed task

我有一个程序可以从位于不同物理位置的 2 reader 中读取一些值。对于一个 reader 我知道我可以这样写:

private async void waitForReading()
{
    string result = await readFromReader1();    
    return result;
}

private async Task<string> readFromReader1()
{
    //poll until value detected
    return reader1Value;
}

private async Task<string> readFromReader2()
{
    //poll until value detected
    return reader2Value;
}

但是,如果我从两个 reader 中读取并在其中一个任务返回时继续执行怎么办?

我想达到的效果是这样的:

private async void waitForReading()
{
    string result = await readFromReader1() || readFromReader2();    
    return result;
}

可能吗?

通过调查类似的问题: Run two async tasks in parallel and collect results in .NET 4.5

我受到 bart 发布的 Task.WhenAll 方法的启发,发现 Task.WhenAny(Task[]) 是我需要的。

怎么样Task.WaitAny

Task<String> task1 = readFromReader1();
Task<String> task2 = readFromReader2();
String result = Task.WhenAny(new Task[]{task1, task2}).Result;

您问题的基本答案是使用 WhenAny:

var task1 = readFromReader1Async();
var task2 = readFromReader2Async();
return await await Task.WhenAny(task1, task2);

但是,还有一些其他注意事项。

您在实施中提到了 "polling"。如果另一个 reader 已经返回值,您可能希望 取消 这种操作。考虑使用 CancellationToken 启用取消。

考虑如何对来自 "reader devices" 的数据建模。如果您总是只想按需查询它们,那么 async 方法就可以了。但是,如果他们的数据可以随时更改(我怀疑是这种情况),那么您可能需要考虑设置一个 permanent 轮询并将其作为事件使用 ;在这种情况下,Reactive Extensions 将是更合适的模型。