我有一个web服务器,有一个定期的作业合并和发送记录(很多请求日志)。
Task.Run(() =>
{
while (true)
{
try
{
MergeAndPutRecords();
}
catch (Exception ex)
{
Logger.Error(ex);
}
}
});在MergeAndPutRecords函数中,有代码合并记录和异步函数返回任务发送记录。(很明显,这是亚马逊Kinesis的PutRecordBatchAsync。)
那么,如果我调用该函数而没有等待关键字,会发生什么呢?函数是否在分离的线程上运行?这里说不是。那么返回任务意味着什么呢?这里说异步方法不需要等待关键字
那么我的定期工作和PutRecordBatchAsync是同时处理的吗?我知道异步和并发是不同的。但是没有等待关键字,它们在同一个线程中。哪一个会先被处决?我很困惑..。
会有大量的记录需要合并并实时发送。所以我认为必须同时执行。
发布于 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.WaitAll或Parallel.ForEach对集合进行处理,对于异步处理,理想的建议是在任何地方都不要有Task.Run,它的首选是从入口点到Async,就像在MVC情况下可能的那样,控制器可以是异步的。使用Task.WhenAll代表任务将多个调用组合在一起,然后等待。即使在代码中使用Task.Run,也可以使用async lambda执行异步调用。
摘要:
它强制在异步调用中使用await,否则它们的async关键字在该上下文中是无用的,并且是的,await将等待IO调用返回,然后再继续执行,尽管进程中没有阻塞线程。
发布于 2017-12-22 09:18:15
如果一个方法返回一个Task,那么最好在某个时候观察该Task的结果。它可能是声明的返回值,也可能是异常。如果要在方法继续之前观察该任务,建议使用await。
在这种情况下,您可能应该观察由Task返回的PutRecordBatchAsync的结果。您可能想知道调用是否由于任何原因而失败,因为这可能表明您的记录没有存储!
在您给出的示例代码中,您将发现在上一次调用完成之前对MergeAndPutRecords进行后续调用。你确定这是故意的吗?
https://stackoverflow.com/questions/47938520
复制相似问题