C#异步等待奇怪的行为

时间:2016-06-10 13:51:45

标签: c# async-await

我是C#的新手,现在我正在尝试了解async / await feautures。所以我创建了小沙盒应用程序:

namespace sandbox
{
public class Test
{
    public async Task<string> GetItemsAsync()
    {
        var a = await Task1();
        var b = await Task2();
        var c = await Task3();

        return a + b + c;
    }

    public string GetItems()
    {
        return _T1() + _T2() + _T3();
    }

    private readonly int cycles = 100000000;

    private async Task<string> Task1()
    {
        return await Task.Factory.StartNew(_T1);
    }

    private async Task<string> Task2()
    {
        return await Task.Factory.StartNew(_T2);
    }

    private async Task<string> Task3()
    {
        return await Task.Factory.StartNew(_T3);
    }

    // long running operation
    private string _T1()
    {
        for (int i = 0; i < cycles; i++) ;
        for (int i = 0; i < cycles; i++) ;
        return "One";
    }

    // long running operation
    private string _T2()
    {
        for (int i = 0; i < cycles; i++) ;
        for (int i = 0; i < cycles; i++) ;
        return "Two";
    }

    // long running operation
    private string _T3()
    {
        for (int i = 0; i < cycles; i++) ;
        for (int i = 0; i < cycles; i++) ;
        return "Three";
    }
}

class Program
{
    static void Main(string[] args)
    {
        var t = new Test();

        Console.WriteLine("Async");
        Stopwatch sw = new Stopwatch();
        sw.Start();
        var result = t.GetItemsAsync();
        Console.WriteLine(result.Result);
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        Console.WriteLine("Sync");
        sw.Restart();
        var strResult = t.GetItems();
        Console.WriteLine(strResult);
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        Console.ReadLine();
    }
}
}

但结果很奇怪:

Async
OneTwoThree
1754
Sync
OneTwoThree
1506

异步方法的运行时间比类似的同步方法长。对我来说,看起来异步方法同步运行,但我无法弄清楚原因。

2 个答案:

答案 0 :(得分:4)

因此:

var a = await Task1();
var b = await Task2();
var c = await Task3();

在您开始Task2之前,您已等待Task1完成。因此,您并没有并行运行它们,而是按顺序运行它们。

如果要启动所有3个任务,然后等待它们完成,则必须将此方法更改为:

public async Task<string> GetItemsAsync()
{
    var t1 = Task1();
    var t2 = Task2();
    var t3 = Task3();

    var a = await t1;
    var b = await t2;
    var c = await t3;

    return a + b + c;
}

或者只是最后一部分:

return (await t1) + (await t2) + (await t3);

此外,此代码是反模式:

private async Task<string> Task3()
{
    return await Task.Factory.StartNew(_T3);
}

您在此处不需要async/await,因为您在子任务返回后,您在此方法中没有再做任何工作了。

而是简单地将此方法(及其兄弟姐妹)重写为:

private Task<string> Task3()
{
    return Task.Factory.StartNew(_T3);
}

答案 1 :(得分:1)

我怀疑其目的是让所有三个任务并行完成。这是如何实现的选择之一:

public async Task<string> GetItemsAsync()
{
    var a = Task1();
    var b = Task2();
    var c = Task3();

    return string.Concat(await Task.WhenAll(a, b, c));
}