异步方法彼此等待

Mr *_*nce 0 .net c# async-await

我正在尝试运行异步程序.
主要有:

using System;
using System.Threading.Tasks;

namespace Test
{
class Program
{
    static void Main(string[] args)
    {
        RunTestsAsync().Wait();
    }

    private async static Task RunTestsAsync()
    {
        var a = new SlowString("ab", true);
        var b = new SlowString("c", true);

        var result1 = a.Equal(b);
        var result2 = b.Last(b);
        var result3 = b.GreaterThen(a);

        result1.Wait();
        result2.Wait();
        result3.Wait();

        Console.WriteLine();
        Console.WriteLine("Results: {0},   {1},   {2}", result1.Result, result2.Result, result3.Result);
        Console.WriteLine();
    }
}
}
Run Code Online (Sandbox Code Playgroud)

这是第二个文件:

using System;
using System.Threading.Tasks;

namespace Test
{
class SlowString
{
    private readonly string str;
    private readonly bool msg;
    private readonly int delay;

    public SlowString(string str, bool msg = false, int delay = 30)
    {
        this.str = str;
        this.msg = msg;
        this.delay = delay;
    }

    public async Task<bool> Equal(SlowString other)
    {
        if(msg) Console.WriteLine("SlowString Equals Started");

        Task.Delay(delay).Wait();
        bool result = await Task.Run(() => { return str.Equals(other.str); });

        if (msg) Console.WriteLine("SlowString Equals Ended");

        return result;
    }

    public async Task<bool> GreaterThen(SlowString other)
    {
        if (msg) Console.WriteLine("SlowString GreaterThen Started");

        Task.Delay(delay).Wait();
        bool result = await Task.Run(() => { return str.CompareTo(other.str) > 0 ? true : false; });

        if (msg) Console.WriteLine("SlowString GreaterThen Ended");

        return result;
    }

    public async Task<SlowString> Last(SlowString other)
    {
        if (msg) Console.WriteLine("SlowString Last Started");

        Task.Delay(delay).Wait();
        SlowString result = await Task.Run(() => { return str.CompareTo(other.str) > 0 ? this : other; });

        if (msg) Console.WriteLine("SlowString Last Ended");

        return result;
    }

    public override string ToString()
    {
        return str;
    }
}
}
Run Code Online (Sandbox Code Playgroud)

问题是我的程序总是等待以前的计算完成,所以我得到:

SlowString Equals Started
SlowString Equals Ended
SlowString Last Started
SlowString Last Ended
SlowString GreaterThen Started
SlowString GreaterThen End

即使有更大的延迟,如3000ms程序stil等待直到计算result1,
然后转到result2并计算它,然后才进一步.

我想我真的尝试了一切.请给我一些线索.

V0l*_*dek 6

您正在呼叫.Wait(),正如其名称所暗示的那样,等待任务完成.它会阻止执行.所以,第一件事是从来没有打电话.Wait().Result或任何类似的.始终使用await您的async方法.

但是,当您尝试并行运行任务时,只需更改.Wait()await不会执行操作.在这种情况下,您的例程看起来应该更像:

var result1 = Task.Run(() => a.Equal(b));
var result2 = Task.Run(() => b.Last(b));
var result3 = Task.Run(() => b.GreaterThen(a));

await Task.WhenAll(new [] {result1, result2, result3});
Run Code Online (Sandbox Code Playgroud)

在其他说明:

Task.Delay(delay).Wait();
Run Code Online (Sandbox Code Playgroud)

也应该是

await Task.Delay(delay);
Run Code Online (Sandbox Code Playgroud)

像这样的线条:

bool result = await Task.Run(() => { return str.CompareTo(other.str) > 0 ? true : false; });
Run Code Online (Sandbox Code Playgroud)

除了应用开销之外不做任何事情:你在线程池上调用一个新任务并立即等待结果.它同步包裹在人为的异步性中.这个:

bool result = str.CompareTo(other.str) > 0 ? true : false;
Run Code Online (Sandbox Code Playgroud)

由于缺乏开销,可能会更快地运行.

你的Main方法应该是:

static async Task Main(string[] args)
{
    await RunTestsAsync();
}
Run Code Online (Sandbox Code Playgroud)