我一直在尝试理解C#中的async / await和Task,但是尽管观看了YouTube视频,阅读了文档并参加了Pluralsight课程,但都以惨败告终。
我希望有人能够回答这些稍微抽象的问题,以帮助我理解。
1. 为什么他们说使用async / await可以实现“异步”方法,而单独的async关键字什么也不做,而await关键字会添加一个暂停点?难道添加一个暂停点不是强制方法以同步方式工作,即在移动到下一个任务之前完成由await标记的任务吗?
2. 明显地,除了事件处理程序之外,您不应该使用async void,那么如何正常调用异步方法?似乎为了使用await关键字调用异步方法,调用它的方法/类本身需要被标记为async。我看过的所有示例都用一个事件处理程序“启动”了一个async void方法。如何“逃脱”这种包装async / await来运行方法呢?
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调用它,否则你会得到消息'Because this call is not awaited..',因此添加一个await将导致该执行点同步等等。
希望这能帮助你更好地理解。
Task.Run
只是将一些工作投放到线程池中。因此,我认为在Task.Run
中的代码与调用代码完全独立。您可以将其视为相对于调用线程异步运行,但它与async
/await
使用的异步方式完全不同,因此我会使用术语“并行”来描述Task.Run
而不是“异步”。您可能会发现我的异步介绍有所帮助。 - Stephen Cleary