我有一个Web服务器,并且有定期作业合并和发送记录(许多请求日志)。
Task.Run(() =>
{
while (true)
{
try
{
MergeAndPutRecords();
}
catch (Exception ex)
{
Logger.Error(ex);
}
}
});
在MergeAndPutRecords
函数中,有代码合并记录和异步函数返回任务发送记录。 (实际上它是亚马逊Kinesis Firehose的PutRecordBatchAsync。)
如果我在没有await关键字的情况下调用该函数会发生什么?函数是否在单独的线程上运行? Here says it is not。那么什么是返回任务手段? Here表示没有等待关键字的异步方法意味着
- 在当前线程上启动异步方法。忽略所有结果(包括例外)。
醇>
然后同时处理我的定期作业和PutRecordBatchAsync?我知道asynchronouse和concurrent是不同的。但是没有await关键字,它们在同一个线程中。首先执行哪一个?我很困惑......
需要合并并实时发送大量记录。所以我认为它必须同时执行..
答案 0 :(得分:7)
然后同时处理我的定期作业和PutRecordBatchAsync?
使用Task API可以确保它们是并发执行的(使用线程池),但是您需要了解内存并发操作与基于IO的并发之间的区别。
虽然在内存并发中确实可以使用Tasks获益,但是一旦执行IO调用根本不需要线程,因为它依赖于硬件并发,如果它曾经使用过该线程,它会做的就是等待IO呼叫返回,从而浪费宝贵的系统资源并降低系统可扩展性
你的情况是基于IO的并发性,当你调用基于远程/网络的API时,async-await如何在这里起作用?
确实如此异步操作将释放线程上下文,在Windows上它将使用IO完成端口(排队机制)来执行异步调用,而调用线程用于调度其他类似的调用,它只需要线程上下文在返回IO调用以提供响应时,如果它不是UI调用,则使用ConfigureAwait(false)
,以便可以使用任何线程上下文来传递响应。
如果您没有使用等待异步?
,该怎么办?
调用意味着异步变为同步,并且会立即影响系统可伸缩性,因为线程现在被阻止,对于长时间运行的IO操作来说更糟糕。你有没有看到JavaScript框架如何总是对服务器API进行AJAX(异步)调用,因此可以做更多的工作来阻止浏览器线程。
一般情况下,在内存处理中,您将创建一定数量的任务并使用Task.WaitAll
或Parallel.ForEach
处理集合,对于异步处理,理想情况下建议不要{{1}在任何地方,它首选从入口点到Task.Run
,就像MVC一样,控制器可以是异步的。使用Async
代表任务将多个呼叫组合在一起,然后等待。即使您在代码中使用Task.WhenAll
,也请使用Task.Run
执行异步调用
摘要:
它必须使用async lambda
进行异步调用,否则它们await
关键字在该上下文中是无用的,而async
将等待IO调用在继续执行之前返回,尽管流程中没有阻止任何线程
答案 1 :(得分:0)
如果方法返回Task
,则最好在某个时刻观察Task
的结果。它可能是声明的返回值,也可能是例外。如果您希望在方法继续之前观察该任务,则建议使用await
。
在这种情况下,您应该观察Task
返回的PutRecordBatchAsync
的结果。您可能想知道呼叫是否因任何原因失败,因为这可能表明您的记录未被存储!
在您提供的示例代码中,您会发现在上一次调用完成之前,您将对MergeAndPutRecords
进行后续调用。你确定这是有意的吗?