首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当您不使用await关键字调用异步方法时,会发生什么?

当您不使用await关键字调用异步方法时,会发生什么?
EN

Stack Overflow用户
提问于 2017-12-22 08:53:40
回答 2查看 14.3K关注 0票数 16

我有一个web服务器,有一个定期的作业合并和发送记录(很多请求日志)。

代码语言:javascript
复制
Task.Run(() =>
{
    while (true)
    {
        try
        {
            MergeAndPutRecords();
        }
        catch (Exception ex)
        {
            Logger.Error(ex);
        }
    }
});

MergeAndPutRecords函数中,有代码合并记录和异步函数返回任务发送记录。(很明显,这是亚马逊Kinesis的PutRecordBatchAsync。)

那么,如果我调用该函数而没有等待关键字,会发生什么呢?函数是否在分离的线程上运行?这里说不是。那么返回任务意味着什么呢?这里说异步方法不需要等待关键字

  1. 在当前线程上启动异步方法。忽略所有结果(包括异常)。

那么我的定期工作和PutRecordBatchAsync是同时处理的吗?我知道异步和并发是不同的。但是没有等待关键字,它们在同一个线程中。哪一个会先被处决?我很困惑..。

会有大量的记录需要合并并实时发送。所以我认为必须同时执行。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-22 10:33:22

那么我的定期工作和PutRecordBatchAsync是同时处理的吗?

使用Task,您可以确保它们是并发执行的(使用线程池),但是您需要理解内存并发操作与基于IO的并发性之间的区别。

虽然在内存并发中使用任务确实有好处,但一旦执行IO调用就根本不需要线程,因为它依赖于硬件并发性,如果它使用该线程,那么它所做的一切都会等待IO调用的返回,从而浪费宝贵的系统资源并降低系统的可伸缩性。

您的情况是基于IO的并发性,正如您所称的基于远程/网络的API,异步等待在这里有什么帮助?

好的,真正的异步操作将释放线程上下文,在windows上它将使用IO完成端口(队列机制)来执行异步调用,而调用线程则用于分派其他类似的调用,在IO调用返回时它只需要线程上下文来服务响应,如果它不是UI调用,则使用ConfigureAwait(false),以便可以使用任何线程上下文来传递响应。

如果您不使用具有异步的等待呢?

异步调用将成为同步调用,并将立即影响系统的可伸缩性,因为线程现在被阻塞,更糟糕的是长期运行的IO操作。您是否见过JavaScript框架总是对服务器API进行AJAX (异步)调用,因此W/o阻塞浏览器线程是可能的。

通常,在内存处理中,您将创建一定数量的任务,并使用Task.WaitAllParallel.ForEach对集合进行处理,对于异步处理,理想的建议是在任何地方都不要有Task.Run,它的首选是从入口点到Async,就像在MVC情况下可能的那样,控制器可以是异步的。使用Task.WhenAll代表任务将多个调用组合在一起,然后等待。即使在代码中使用Task.Run,也可以使用async lambda执行异步调用。

摘要:

它强制在异步调用中使用await,否则它们的async关键字在该上下文中是无用的,并且是的,await将等待IO调用返回,然后再继续执行,尽管进程中没有阻塞线程。

票数 8
EN

Stack Overflow用户

发布于 2017-12-22 09:18:15

如果一个方法返回一个Task,那么最好在某个时候观察该Task的结果。它可能是声明的返回值,也可能是异常。如果要在方法继续之前观察该任务,建议使用await

在这种情况下,您可能应该观察由Task返回的PutRecordBatchAsync的结果。您可能想知道调用是否由于任何原因而失败,因为这可能表明您的记录没有存储!

在您给出的示例代码中,您将发现在上一次调用完成之前对MergeAndPutRecords进行后续调用。你确定这是故意的吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47938520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档