我正在尝试测试.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关键字就是这样,只要没有使用等待的结果,程序就会继续这样做。
也许我执行的任务错了?!
答案 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