C# 异步等待阻塞,怎么了?

C# 异步等待阻塞,怎么了?,c#,.net,async-await,C#,.net,Async Await,我正在尝试测试.NET的异步/等待功能。我在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 s

我正在尝试测试.NET的异步/等待功能。我在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!";
    }
}
void Main(字符串[]args)
{
Test.DoStuff().Wait();
}
//在此处定义其他方法和类
公开课考试
{
公共异步静态任务DoStuff()
{
字符串s1=“你好1”;
string s2=“Hello 2”;
var s3=等待测试。Gimme();
字符串s4=“Hello 4”;
控制台写入线(s1);
控制台写入线(s2);
控制台写入线(s3);
控制台写入线(s4);
}
公共异步静态任务Gimme()
{
返回等待任务。运行(()=>RetString());
}
公共静态字符串RetString()
{
控制台写入线(“开始”);
对于(int i=0;i<90000000;i++)
{
字符串s=“FOO”;
s=s+s;
s=s+s;
}
控制台。写入线(“结束”);
返回“任务你好3!”;
}
}
据我所知,我认为代码会一直执行到s3再次被使用=>Console.WriteLine(s3)

我错过了什么?!我认为wait关键字可以让程序继续做它的事情,只要不使用等待的结果


也许我执行任务错了

Await实际上会在进程完全完成之前保持执行。因此,您的测试方法应该完全构建整个RetString,然后将其返回给Gimme,然后Gimme将该字符串返回给var s3,然后继续处理

来自Microsoft:等待运算符应用于异步方法中的任务,以暂停该方法的执行,直到等待的任务完成。这项任务是正在进行的工作。详情请参阅:

我认为wait关键字可以让程序继续做它的事情,只要不使用等待的结果

你错了。
wait
关键字将等待该操作。也就是说,关键字不是返回可能在以后完成操作的
任务
,而是等待该任务的结果。(在本例中为字符串。)

所以当你这样做的时候:

var s3 = await Test.Gimme();
string s4 = "Hello 4";
async
操作的结果可用之前,第二行不会执行。与此相反:

var s3 = Test.Gimme();
string s4 = "Hello 4";
它不等待操作完成,而是在
s3
中引用
任务,该任务可能稍后完成(等待)

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

大多数
async
方法在逻辑上是同步的,但会包装底层异步操作,并将选项公开到更高的级别,以不阻塞这些操作。保持“一路异步”的口头禅,许多这样的方法提供“传递异步性”,并允许顶级UI异步处理底层I/O

我错过了什么?!我认为wait关键字可以让程序继续做它的事情,只要不使用等待的结果

你是对的;你的困惑就是“做自己的事”的意思。在等待结果时所做的“工作”是DoStuff的调用者的“工作”,它是Main。当DoStuff由于任务未完成而无法取得进展时,调用方会做什么它调用Wait。结果就是这样


您说过您希望等待结果,这意味着您希望调用方在异步处理任务时执行任何操作。打电话的人说“我无事可做,只能同步等待*。如果调用方在调用Wait之前做了一些其他工作,那么您将看到该工作正在完成。

Wait
将等待等待的对象完成,具体执行方式取决于上下文,但这意味着
string s4=…
Test.Gimme
完成之前不会执行。如果您想实现所需的行为,请调用
Console.WriteLine(等待s3)。这将在打印
s1
s2
之前开始执行Gimme()。如果您想模拟工作而不实际编写计算无用suff的循环,请等待任务。延迟。我对您的代码感到困惑。
返回等待任务的意义是什么。只需在
返回任务上运行…
,然后运行、、
?我觉得很奇怪,当你可以说“我的任务是做三明治”时,你会说“我的任务是等待完成做三明治的任务”。没有等待,我得到了一个同步方法(编译器警告)。谢谢,一个大细节,完全错了。现在我想知道为什么LinqPad会在控制台中放置一个“waiting…”并在稍后替换它…我知道它这样做是因为它被延迟了。。。我猜这是一个很好的LinqPad功能。该死的。。。你说得对,我想我不知怎么搞混了。谢谢