0

我从这里阅读了本指南http://blog.stephencleary.com/2012/02/async-and-await.html

在这里,我得到了一些代码,但对我来说不是很清楚。

1)

public async Task DoOperationsInParallelAsync()
{
  Task[] tasks = new Task[3];
  tasks[0] = DoOperation0();
  tasks[1] = DoOperation1();
  tasks[2] = DoOperation2();

  // At this point, all three tasks are running in parallel.

  // Now, we await them all.
  await Task.WhenAll(tasks);
}

在上面我们创建了多个任务,但假设当所有任务将并行运行时,DoOperation2() 可能首先完成,DoOperation0() 和最后 DoOperation1() 完成。如果我想在控制台窗口中显示像 DoOperation2() 这样的消息,那么我该怎么做。当多个正在运行时,我怎么能检测到哪个任务完成了。

2)当我们在async/await的帮助下运行任何函数时,它是作为后台线程还是前台线程运行的。

3)

public async Task<int> GetFirstToRespondAsync()
{
  // Call two web services; take the first response.
  Task<int>[] tasks = new[] { WebService1(), WebService2() };

  // Await for the first one to respond.
  Task<int> firstTask = await Task.WhenAny(tasks);

  // Return the result.
  return await firstTask;
}

我不明白为什么这个人写了等待第一个回复。

// 等待第一个响应。任务 firstTask = 等待 Task.WhenAny(tasks);

为什么是第一个......为什么不是第二个,因为这里有两个任务正在运行。

请指导我并消除我的困惑。谢谢

4

3 回答 3

1

您可以对将更新进度的每个任务使用 ContinueWith 方法。

所以...

foreach (var t in tasks)
{
   t.ContinueWith(Console.WriteLine("Hey I am done"));
}
于 2013-11-14T12:06:03.017 回答
1
  1. 因为它是一个控制台应用程序,所以您需要等待任务完成。以下是如何从任务返回字符串的示例:

    class WhenAny
    {
        public static async Task<string> GetFirstToRespondAsync()
        {
            // Call two web services; take the first response.
            Task<string>[] tasks = new[] { Task1(), Task2() };
    
            // Await for the first one to respond.
            Task<string> firstTask = await Task.WhenAny(tasks);
    
            // Return the result.
            return firstTask.Result;
        }
    
        private static async Task<string> Task1()
        {
            await Task.Delay(3000);
            return "Task1";
        }
    
        private static async Task<string> Task2()
        {
            await Task.Delay(1000);
            return "Task2";
        }
    }
    

    从 Main 函数调用它,如下所示:

    static void Main(string[] args)
    {
        var t = WhenAny.GetFirstToRespondAsync();
        t.ContinueWith((taskName) =>
            {
                string result = taskName.Result;
                Console.WriteLine("Result: " + result);
            });
    
        t.Wait();
        Console.ReadLine();
    }
    

    这应该返回首先完成的任务,您可以从Task.Result

  2. 等待一个方法本身并不会创建一个额外的线程。它所做的是创建一个回调以避免阻塞当前线程(通常这用于不阻塞 UI 线程)。

  3. WhenAny当最早完成的操作返回时返回。这并不意味着您提供的列表中的第一个。因此,上面的代码将始终显示 1000,即使它是第二个任务。

为了完整起见,这里与WhenAll 相同:

class WhenAll
{

    public static async Task<string[]> WaitForAllAsync()
    {
        // Call two web services; take the first response.
        Task<string>[] tasks = new[] { Task1(), Task2(), Task3() };

        // Wait for a tasks
        string[] results = await Task.WhenAll(tasks);

        // Return the result.
        return results;
    }

    private static async Task<string> Task1()
    {
        await Task.Delay(3000);
        return "Task1";
    }

    private static async Task<string> Task2()
    {
        await Task.Delay(1000);
        return "Task2";
    }

    private static async Task<string> Task3()
    {
        await Task.Delay(5000);
        return "Task3";
    }

}

并称之为:

static void Main(string[] args)
{
     var t = WhenAll.WaitForAllAsync();
     t.ContinueWith((task) =>
     {
         string[] result = task.Result;
         foreach(string taskname in result)
         {
             Console.WriteLine("Result: " + taskname);
         }
     });

     t.Wait();
     Console.ReadLine();

}
于 2013-11-14T12:28:37.287 回答
1

1)传入一个回调函数

public async Task DoOperationsInParallelAsync(Action<Task<int>> completed)
{
    var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    var tasks = new[] { DoOperation0(), DoOperation1(), DoOperation2() };

    var completedTasks = tasks.Select(x => x.ContinueWith(completed, uiScheduler)).ToArray();

    await Task.WhenAll(completedTasks);
}

private async void Button1_Click(object sender, EventArgs e)
{
    await DoOperationsInParallelAsync(t => {
        Label1.Text = string.Format("Task finished with {0}", t.Result);
    });
}

2)Task将在线程池上运行,除非您将其指定为长时间运行或提供TaskScheduler.

3)当只有第一个结果很重要(计算是多余的或时间敏感的)时,例如从反映相似数据的不同供应商那里获取股票价格。

于 2013-11-14T12:15:48.740 回答