C# Asp.NETWebAPI运行MongoDB查询/异步保存
我目前正在尝试确定何时使用Task.Run,何时不使用 在我的项目中,我使用WebApi结合MongoDB来存储帐户信息 因此,对于下面的示例代码,在客户端调用中使用Submit或SumbitAsync方法会更好吗C# Asp.NETWebAPI运行MongoDB查询/异步保存,c#,mongodb,asynchronous,asp.net-web-api,task,C#,Mongodb,Asynchronous,Asp.net Web Api,Task,我目前正在尝试确定何时使用Task.Run,何时不使用 在我的项目中,我使用WebApi结合MongoDB来存储帐户信息 因此,对于下面的示例代码,在客户端调用中使用Submit或SumbitAsync方法会更好吗 public class TestController : ApiController { [HttpPost] public void Submit() { DoSave(); } public async Task Sub
public class TestController : ApiController
{
[HttpPost]
public void Submit()
{
DoSave();
}
public async Task SubmitAsync()
{
await Task.Run(() => DoSave());
}
private void DoSave()
{
myMongoDbCollection.Save(new TestEntity());
}
}
MongoDB C#驱动程序目前不支持异步方法。使用
任务没有意义。请在此处运行
在ASP.NET中使用异步I/O的目的是释放线程,以便它可以处理其他请求,直到I/O完成。同时,不会阻塞任何线程。当I/O操作完成时,I/O完成端口将发出信号,您的方法将恢复
使用Task.Run
,您只需将其延迟到线程池线程,并使该线程阻塞等待I/O
换句话说,如果客户端不支持异步I/O,您的一个线程将始终阻塞。因此,您最好同步完成这一切,并避免不必要的上下文切换
发件人:
在使用Wait with Task时,会(至少)引入四个效率问题。请在ASP.NET中运行:
- 额外(不必要)线程切换到任务。运行线程池线程。类似地,当该线程完成请求时,它必须输入请求上下文(该上下文不是实际的线程切换,但有开销)
- 创建了额外(不必要)的垃圾。异步编程是一种折衷方法:以更高的内存使用率为代价来提高响应速度。在这种情况下,您最终会为完全不必要的异步操作创建更多的垃圾
- ASP.NET线程池启发被任务抛出。请“意外”借用线程池线程运行。我在这方面没有太多经验,但我的直觉告诉我,如果意外任务非常短,那么启发式应该能够很好地恢复,如果意外任务持续时间超过两秒钟,则不会像处理得那么优雅
- ASP.NET无法提前终止请求,即如果客户端断开连接或请求超时。在同步情况下,ASP.NET知道请求线程并可以中止它。在异步情况下,ASP.NET不知道辅助线程池线程“用于”该请求。可以通过使用取消令牌来解决这个问题,但这超出了本文的范围