是否可以并行执行两个异步方法?

时间:2014-10-21 17:55:36

标签: c# asynchronous async-await

如果我执行两个任务,我可以同时执行这两个任务,并等到两个任务完成。使用此代码:

Task<bool> tsk01 = Task.Run(()=> my code; return true);
Task<bool> tsk02 = Task.Run(()=> my code; return true);
Task.WaitAll(tsk01, tsk02);

//next code

在这种情况下,以下代码仅在所有任务完成时执行。但是应用程序没有被阻止。

但是,如果我有这段代码:

private async void Button_Click_2(object sender, RoutedEventArgs e)
{
    Task<bool> tsk01 = miMetodoAsync01();
    Task<bool> tsk02 = miMetodoAsync02();
    Task.WaitAll(tsk01, tsk02);
}

private async Task<bool> miMetodoAsync02()
{
    return await TaskEx.Run<bool>(() =>
        {
            Int64 resultado = 0;
            for (Int64 i = 1; i < 1000000000; i++)
            {
                resultado = resultado + 1;
            }

            return true;

        }).ConfigureAwait(false);
    }



    private async Task<bool> miMetodoAsync01()
    {
        return await TaskEx.Run<bool>(() =>
        {
            Int64 resultado = 0;
            for (Int64 i = 1; i < 1000000000; i++)
            {
                resultado = resultado + 1;
            }

            return true;

        }).ConfigureAwait(false);
    }

在第二个选项中,应用程序被阻止,因为WaitAll似乎在等待从未发生过的任务的响应。

为什么在第一种情况下应用程序没有被阻止,而在第二种情况下它是?

2 个答案:

答案 0 :(得分:5)

您的示例都将阻止UI线程。这就是Task.WaitAll的含义。

但是,您可以使用TaskEx.WhenAll

await TaskEx.WhenAll(tsk01, tsk02);

答案 1 :(得分:1)

方法Task.WaitAll将阻止UI线程,因为它在继续之前等待所有任务返回。

您为创建Task创建的代码示例基本相同(尽管写的方式稍有不同)。返回Task<bool>

不同之处在于在两个lambda表达式中运行的函数。你的第一个例子有一个&#34;我的代码&#34;参考和返回。第二个例子是你创建了两个计数器。

如果你的代码&#34;我的代码&#34;与第二个示例中创建的计数器的定义不同,或者如果您只在lambda表达式中返回true,那么您将看到一个等待另一个的外观。

简单地返回true将在创建后立即结束线程。其中 - 计数器需要时间来计算(也取决于你的CPU速度)。

如果您将相同的计数器添加到第一个示例的函数中,您会发现两者都占用相同的时间,而Task.WaitAll会阻止您的UI。您可以使用System.Diagnositics.StopWatch类来计时。

    static void Main(string[] args)
    {
        string test = Console.ReadLine();

        System.Diagnostics.Stopwatch t = new System.Diagnostics.Stopwatch();
        t.Start();
        Task<bool> task1 = Task.Run<bool>(() => { return true; });
        Task<bool> task2 = Task.Run<bool>(() => { return true; });
        Task.WaitAll(task1, task2);
        t.Stop();

        Console.WriteLine("Elapsed time: " + t.Elapsed);

        System.Diagnostics.Stopwatch t2 = new System.Diagnostics.Stopwatch();
        t2.Start();
        Task<bool> task3 = asyncMethod1();
        Task<bool> task4 = asyncMethod2();
        Task.WaitAll(task3, task4);
        t2.Stop();

        Console.WriteLine("Elapsed time: " + t2.Elapsed);
        Console.Read();
    }