首页 文章

如何在C#中等待异步工作[关闭]

提问于
浏览
51

我试图了解如何在C#中等待异步工作,有一件事让我很困惑 . 我知道任何使用await关键字的方法都必须用async标记 . 我的理解是当一个带有await关键字的行被命中时,该行下面的代码不会被执行 . 启动异步操作以在await行中继续执行该语句,并将控制返回给可以继续执行的调用方法 .

问题1:这个假设是正确的还是仍然执行await关键字下面的代码?

其次假设我调用了一个服务方法async,需要返回它的结果 . return语句在await关键字下面 .

问题2:在异步调用完成之后或之前,返回语句是什么时候命中的?

问题3:我想使用该服务调用的结果和异步操作不会导致我希望在返回结果时命中调用方法 . 我知道这可以使用Result属性完成,该属性使调用同步 . 但是,在数据库操作中使用异步是什么原因导致它们在大多数应用程序中实际占用80%的时间 .

问题4:如何在数据库操作中使用异步?有可能并推荐?

问题5:在哪个场景中异步操作有用似乎每个api现在只是在没有理由的情况下进行异步操作?还是我错过了使用异步操作的意义?

我的意思是说api正在制造asyn方法而没有理由是因为方法必须返回一些东西并且直到计算得出它们如何返回所以在本质中这个调用仍然不会被阻塞,因为它将是无用的直到结果被退回?

2 回答

  • 55

    MSDN explains everything .

    我理解,虽然有时香草文档(特别是来自MSDN)很难适用于您的特定情况,所以让我们回顾一下您的观点 .

    问题#1:这个假设是正确的还是仍然执行await关键字下面的代码?

    “await”关键字下面的代码只会在异步调用完成时执行 . 同时,由于您的方法被标记为“async”,因此控制将返回给您的方法的调用者,直到您的方法完成 . 从上面的MSDN链接:

    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
    
    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();
    
    // The await operator suspends AccessTheWebAsync. 
    //  - AccessTheWebAsync can't continue until getStringTask is complete. 
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    //  - Control resumes here when getStringTask is complete.  
    //  - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask;
    

    我认为这些评论很有说服力 .

    其次假设我调用了一个服务方法async,需要返回它的结果 . return语句在await关键字下面 .

    问题#2:在异步调用完成之后或之前,返回语句是什么时候命中的?

    后 .

    问题3:我想使用该服务调用的结果和异步操作不会导致我希望在返回结果时命中调用方法 . 我知道这可以使用Result属性完成,该属性使调用同步 . 但是,在数据库操作中使用异步是什么原因导致它们在大多数应用程序中实际占用80%的时间 .

    假设您需要进行三次不相关的数据库查询来完成服务,然后根据结果执行计算,然后完成 . 如果按顺序执行此操作,则必须等到每个操作完成 . 如果您使用异步调用,那么C#将并行运行三个查询,您的服务可能会更快完成 .

    此外,返回Task的操作可用作Futures . 请参阅MSDN on Futures,其中讨论了如何基于期货并行化工作并合并结果的几种模式 .

    如果您的服务只需要一个数据库调用,那么将它称为异步肯定会更糟 .

    问题4:如何在数据库操作中使用异步?有可能并推荐?

    ADO.NET现在包含异步方法ReadAsync and NextResultAsync .

    这绝对是可能的,至于推荐这个讨论比我写的更完整here .

    问题5:在哪个场景中,异步操作会很有用,似乎每个api现在只是在没有理由的情况下进行异步操作?还是我错过了使用异步操作的意义?

    异步操作对于轻松并行化任何长时间运行的操作非常有用,而不会遇到线程问题 . 如果你的方法只做一件事,或者一系列简单(快速)的事情,那么是的,去异步是没用的 . 但是,如果您有多个长时间运行的操作,那么通过异步并行处理它们比管理线程更容易且更不容易出错 .

  • 14

    大多数问题都在official中得到解答documentation以及我写的an intro post .

    问题4:如何在数据库操作中使用异步?可能吗

    实体框架6(目前处于测试阶段)支持 async . 较低级别的数据库API以这种或那种方式支持异步操作 . 其中一些(例如,SQLite)直接支持 async ;其他人需要你编写简单的 async 兼容包装器 .

    ...并推荐?

    是的,除非您正在编写与后端的不可伸缩的单个数据库计算机对话的前端服务器(例如,ASP.NET) . 在这种特定情况下,制作前端刻度是没有意义的,因为无论如何你的后端都无法缩放以匹配它 .

    问题5:在哪个场景中,异步操作会很有用,似乎每个api现在只是在没有理由的情况下进行异步操作?还是我错过了使用异步操作的意义?

    异步操作的好处是:

    • 在客户端(UI)端,您的应用程序保持响应 .

    • 在服务器端,您的应用程序可以更好地扩展 .

相关问题