无法理解异步并等待 [英] Trouble understanding async and await

查看:76
本文介绍了无法理解异步并等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试理解C#中的异步/等待和任务,但是尽管观看了youtube视频,阅读了文档并参加了多元见解的课程,但是却失败了.

I've been trying to understand async/await and Task in C# but have been failing spectacularly despite watching youtube videos, reading documentation and following a pluralsight course.

我希望有人能够帮助回答这些稍微抽象的问题,以帮助我的大脑.

I was hoping someone might be able to help answer these slightly abstract questions to help my brain out.

1.为什么他们说async/await本身启用了async关键字却什么也不做,而await关键字添加了一个悬浮点,则启用了"asynchonrous"方法?不会添加强制该方法同步操作的悬浮点,即在继续操作之前完成等待标记的任务.

1.Why do they say that async/await enables an 'asynchonrous' method when the async keyword on it's own does nothing and the await keyword adds a suspension point? Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.

2.显然,除了事件处理程序之外,您不应该使用异步void,那么如何正常调用异步方法?似乎为了使用await关键字调用异步方法,正在调用自身的方法/类需要标记为异步.我所看到的所有示例都已使用事件处理程序启动"了一个异步void方法.您将如何转义"这种异步/等待的包装来运行该方法?

2.Apparently you are not supposed to use async void except for event handlers, so how do you call an async method normally? It seems that in order to call an async method by using the await keyword, the method/class that is calling it itself needs to be marked as async. All the examples I've seen have 'initiated' an async void method with an event handler. How would you 'escape' this wrapping of async/await to run the method?

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将导致该执行点是同步的,依此类推.

Relating back to 1. this looks like a synchronous method. Execution pauses when it gets to Task.Run, therefore Console.WriteLine("End of method"); will not be executed until the task is finished. Maybe the whole method itself will be executed asynchronously at the point it is triggered in the code? But relating back to 2, you need to call this with an await otherwise you get the message 'Because this call is not awaited..' therefore adding an await will cause that execution point to be synchronous and so on and so.

任何帮助理解这一点的人将不胜感激.

Any help understanding this would be much appreciated.

推荐答案

没有添加强制该方法同步执行的暂停点,即在继续操作之前完成等待标记的任务.

Isn't adding a suspension point forcing the method to act synchronously, i.e. finish the task marked by the await before moving on.

不,您要使用的单词是顺序的",而不是同步的". await生成异步顺序代码. 顺序的"意思是一次一个"; 同步"表示阻塞直到完成".

No, the word you're thinking of is "sequential", not "synchronous". await results in asynchronous sequential code. "Sequential" meaning "one at a time"; "synchronous" meaning "blocking until completed".

您如何正常调用异步方法?

how do you call an async method normally?

使用await.

您如何转义"异步/等待运行该方法的包装?

How would you 'escape' this wrapping of async/await to run the method?

理想情况下,您不要.您一路异步.现代框架(包括ASP.NET MVC,Azure Functions/WebJobs,NUnit/xUnit/MSTest等)都允许您具有返回Task的入口点.较不现代的框架(包括WinForms,WPF,Xamarin Forms,ASP.NET WebForms等)都允许async void入口点.

Ideally, you don't. You go async all the way. Modern frameworks (including ASP.NET MVC, Azure Functions / WebJobs, NUnit / xUnit / MSTest, etc) all allow you to have entry points that return Task. Less-modern frameworks (including WinForms, WPF, Xamarin Forms, ASP.NET WebForms, etc) all allow async void entry points.

因此,理想情况下,您从同步代码中调用异步代码.如果您考虑什么是 异步代码,这是很有意义的:它的全部目的是阻塞调用线程,因此,如果您阻塞异步代码上的调用线程,那么首先您将失去异步代码的所有好处.

So, ideally you do not call asynchronous code from synchronous code. This makes sense if you think about what asynchronous code is: the entire point of it is to not block the calling thread, so if you block the calling thread on asynchronous code, then you lose all the benefits of asynchronous code in the first place.

也就是说,在极少数情况下,您确实需要同步处理代码.例如,如果您正处于向异步过渡的过程中,或者受到强制的库/框架的约束,则您的代码将是同步的,并且不能与async void一起使用.在这种情况下,您可以在我关于棕地异步的文章中使用 hacks之一 a>.

That said, there are rare situations where you do need to treat the code synchronously. E.g., if you are in the middle of a transition to async, or if you are constrained by a library/framework that is forcing your code to be synchronous and won't work with async void. In that case, you can employ one of the hacks in my article on brownfield async.

这篇关于无法理解异步并等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆