异步等待阻塞,有什么问题?

时间:2016-03-07 13:49:48

标签: c# .net async-await

我正在尝试测试.NET的async / await功能。我在LinqPad中设置了一个小测试:

void Main(string[] args)
{
    Test.DoStuff().Wait();
}

// Define other methods and classes here
public class Test
{
    public async static Task DoStuff()
    {
        string s1 = "Hello 1";
        string s2 = "Hello 2";
        var s3 = await Test.Gimme();
        string s4 = "Hello 4";

        Console.WriteLine(s1);
        Console.WriteLine(s2);
        Console.WriteLine(s3);
        Console.WriteLine(s4);
    }

    public async static Task<string> Gimme()
    {
        return await Task.Run<string>(() => RetString());
    }

    public static string RetString()
    {
        Console.WriteLine("Begin");

        for (int i = 0; i < 90000000; i++)
        {
            string s = "FOO";
            s = s + s;
            s = s + s;
        }

        Console.WriteLine("End");
        return "Task Hello 3!";
    }
}

根据我的理解,我认为代码将被执行,直到再次使用s3 =&gt; Console.WriteLine(S3);

我缺少什么?!我认为await关键字就是这样,只要没有使用等待的结果,程序就会继续这样做。

也许我执行的任务错了?!

3 个答案:

答案 0 :(得分:6)

  

我认为await关键字是这样的,只要等待的结果没有被使用,程序就会继续这样做。

你错了。 await关键字将等待该操作。也就是说,关键字等待该任务的结果,而不是返回可能在以后完成操作的Task。 (在这种情况下是一个字符串。)

所以当你这样做时:

var s3 = await Test.Gimme();
string s4 = "Hello 4";

async操作的结果可用之前,第二行不会执行。与此相反:

var s3 = Test.Gimme();
string s4 = "Hello 4";

哪个没有等待操作完成,而只是在Task<string>中引用s3,这可能会在({等待})完成以后。

这里的想法是DoStuff()方法本身将按照命令式编写的顺序执行代码,就像任何其他代码一样。但该代码调用 的东西可能是异步的,因此反过来调用DoStuff()的代码可以选择以异步方式处理它。

大多数async方法在逻辑上是同步的,但是包装底层异步操作并将选项暴露给更高级别以不阻止这些操作。保持事情应该是&#34;完全同步的咒语&#34;,许多这样的方法提供&#34;传递ascynchronicity&#34;并允许顶级UI异步处理底层I / O.

答案 1 :(得分:5)

  

我缺少什么?!我认为await关键字是这样的,只要等待的结果没有被使用,程序就会继续做它的东西。

你是对的;你的困惑是“做它的东西”的意思。在等待结果时完成的“东西”是DoStuff的调用者的“东西”,它是Main。当DoStuff因为任务没有完成而无法取得进展时,调用者会做什么? 呼叫等待。这就是发生的事情!

你说你想要等待结果,这意味着你希望调用者在异步处理任务时做任何事情。调用者说:“我无所事事,只能同步等待*。如果调用者在调用Wait之前做了其他工作,那么你会看到工作正在完成。

答案 2 :(得分:2)

如果完全完成,Await实际上会暂停执行。因此,您的测试方法应该完全构建整个RetString,然后将其返回给Gimme,然后Gimme将字符串返回到var s3,然后继续处理。

来自Microsoft:await运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。该任务代表了正在进行的工更多详细信息,请参见:https://msdn.microsoft.com/en-us/library/hh156528.aspx