麻烦理解异步并等待

我一直在尝试理解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并要求返回类型为voidTask/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

上一篇: Trouble understanding async and await

下一篇: Is this a correct diagram of how async