麻烦理解异步并等待
我一直在尝试理解C#中的异步/等待和任务,但尽管观看了YouTube视频,阅读文档并遵循复数视图课程,但仍然失败壮观。
我希望有人能够帮助回答这些稍微抽象的问题来帮助我解决问题。
1.为什么当async关键字自己什么都不做,并且await关键字添加一个暂停点时,他们说异步/等待会启用“asynchonrous”方法? 不增加一个强制方法同步动作的暂停点,即在继续之前完成await标记的任务。
2.显然,除了事件处理函数外,您不应该使用异步无效函数,所以如何正常调用异步方法? 看起来,为了通过使用await关键字来调用异步方法,调用它的方法/类本身需要被标记为async。 我见过的所有例子都已经用事件处理程序“启动”了一个异步无效方法。 你如何'逃避'异步/等待运行该方法的这种包装?
3。
public async Task SaveScreenshot(string filename, IWebDriver driver)
{
var screenshot = driver.TakeScreenshot();
await Task.Run(() =>
{
Thread.Sleep(2000);
screenshot.SaveAsFile(filename, ScreenshotImageFormat.Bmp);
Console.WriteLine("Screenshot saved");
});
Console.WriteLine("End of method");
}
关联回1.这看起来像一个同步方法。 当它进入Task.Run
时执行暂停,因此Console.WriteLine("End of method");
在任务完成之前不会执行。 也许整个方法本身会在代码中被触发的地方异步执行? 但是回到2,你需要用await来调用它,否则你会得到'因为这个调用没有被等待',所以添加一个await会导致这个执行点是同步的,等等。
任何帮助理解这一点将不胜感激。
不增加一个强制方法同步动作的暂停点,即在继续之前完成await标记的任务。
不,你正在考虑的这个词是“连续的”,而不是“同步的”。 await
异步顺序代码的结果。 “顺序”意思是“一次一个”; “同步”意思是“阻塞直到完成”。
你如何正常调用异步方法?
使用await
。
你如何'逃避'异步/等待运行该方法的这种包装?
理想情况下,你不这样做 。 你一直走异步。 现代框架(包括ASP.NET MVC,Azure函数/ WebJobs,NUnit / xUnit / MSTest等)都允许您拥有返回Task
入口点。 较不现代的框架(包括WinForms,WPF,Xamarin表单,ASP.NET WebForms等)都允许async void
入口点。
因此,理想情况下,您不会从同步代码调用异步代码。 如果您考虑异步代码是什么意思,那么这是有道理的:它的整个目的是不阻塞调用线程,所以如果在异步代码上阻塞调用线程,那么您首先会失去异步代码的所有优点。
也就是说,在极少数情况下,您需要同步处理代码。 例如,如果您正处于向异步转换的过程中,或者受到强制您的代码同步并且无法使用async void
的库/框架的约束。 在这种情况下,您可以在我的关于brownfield async的文章中使用其中一种黑客技术。
你的理解非常好:)。 您似乎缺少的主要观点是.NET中的“异步”方法意味着可以在不阻止调用线程的情况下停止执行的方法。
正如您在(1)中指出的那样, async
关键字基本上允许使用await
并要求返回类型为void
或Task/Task<T>
。 await
只是指示当前的方法暂停执行,直到任务完成。
你在这里失踪的是它暂停当前的方法 。 它不会阻塞该方法正在执行的线程。 这在WPF应用程序的UI线程等情况下非常重要。 挂起方法执行并且所有内容都继续运行,阻塞该线程并且应用程序停止响应。
您通常希望async
调用一直到顶层(如事件处理程序),这样可以提供最大的灵活性并防止出现死锁情况。 然而; 您可以等待Task
返回方法以Wait
完成:
someAsyncMethod.Wait()
或者获取返回值:
var result = someAsyncMethod.Result;
请注意,这两个都是同步的并阻止调用线程。 如果异步任务正在等待调用线程上的其他工作完成,则会造成死锁。
上面应该回答你在(3)中的问题; 该方法本身似乎是同步执行的(这是await/async
的魔力),但是该任务不会阻塞调用线程。
它是异步的,因为您不必等待方法返回。 在您的代码中,您可以调用异步方法并将任务保存在变量中。 继续做其他事情。 稍后,当需要方法结果时,您将等待响应(任务)。
// Synchronous method.
static void Main(string[] args)
{
// Call async methods, but don't await them until needed.
Task<string> task1 = DoAsync();
Task<string> task2 = DoAsync();
Task<string> task3 = DoAsync();
// Do other stuff.
// Now, it is time to await the async methods to finish.
Task.WaitAll(task1, task2, task3);
// Do something with the results.
Console.WriteLine(task1.Result);
Console.ReadKey();
}
private static async Task<string> DoAsync()
{
Console.WriteLine("Started");
await Task.Delay(3000);
Console.WriteLine("Finished");
return "Success";
}
// Output:
// Started
// Started
// Started
// Finished
// Finished
// Finished
// Success
链接地址: http://www.djcxy.com/p/79321.html