等待只有一项任务完成

时间:2016-03-03 21:13:43

标签: c# task-parallel-library

我们说我有两项任务,具有以下要求:

  1. 两者都是异步的。
  2. 两者并行运行
  3. 当他们中的一个完成时,我需要知道哪一个做了。
  4. 我提出了以下代码,但它只是在两个任务开始后挂起(WaitAny函数永远不会返回)。我在Run函数下也得到了一条波浪线,告诉我在其中添加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");
    }
    

1 个答案:

答案 0 :(得分:5)

使用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时拨打this overload。我还将async void替换为async Taskyou should never do asnyc void,除非您使用它来匹配事件处理程序签名。