只等待一个任务完成

Wait for only one task to complete

假设我有两个任务,要求如下:

  1. 两者都是异步的。
  2. 两个 运行 并行
  3. 其中一个完成的那一刻我需要知道哪个完成了。

我想出了以下代码,但它只是在两个任务启动后挂起(WaitAny 函数从不 returns)。我还在 运行 函数下得到一条波浪线,告诉我在其中添加 await,但是当我尝试在 Task.WaitAny 前面添加它时 VS 抱怨。我应该在另一个任务中包装 WaitAny 吗?我做错了什么?

async void Run()
{
    Task task1 = Task1();
    Task task2 = Task2();

    int completedTaskIdx = Task.WaitAny(task1, task2);

    Debug.WriteLine("completedTaskIdx = {0}", completedTaskIdx.ToString());
}

async Task Task1()
{
    Debug.WriteLine("Task 1 Start");
    await Task.Delay(5000);
    Debug.WriteLine("Task 1 Stop");
}

async Task Task2()
{
    Debug.WriteLine("Task 2 Start");
    await Task.Delay(10000);
    Debug.WriteLine("Task 2 Stop");
}

使用asnyc/await、you will cause dedlocks时不要阻塞UI线程。您的 WaitAny() 导致您陷入僵局。请改用 WhenAny,您可以使用 Array.IndexOf( 将返回的任务转换回索引。

async Task Run()
{
    Task task1 = Task1();
    Task task2 = Task2();

    var tasks = new[] {task1, task2};
    Task completedTask = await Task.WhenAny(tasks);

    //It is a good idea to await the retuned task, this is the point a execption would
    //be raised if the task finished with a exception.
    await completedTask;

    int completedTaskIdx = Array.IndexOf(tasks, completedTask);

    //.ToString() will cause you to have a bug, you are calling the 
    //wrong overload of WriteLine. The correct overload will call .ToString() for you.
    Debug.WriteLine("completedTaskIdx = {0}", completedTaskIdx); 
}

我还修复了你的 Debug.WriteLine( 调用中的一个错误,你在哪里调用 this overload when you wanted this overload. I also replaced your async void with async Task, you should never do asnyc void 除非你使用它来匹配事件处理程序签名。