C# 异步控制器方法不返回
当我向该代码发出请求时,该代码挂起(不返回响应):C# 异步控制器方法不返回,c#,asp.net,asp.net-web-api,async-await,C#,Asp.net,Asp.net Web Api,Async Await,当我向该代码发出请求时,该代码挂起(不返回响应): public class MyController : ApiController { public async Task<IQueryable<int>> Get() { return await new Task<IQueryable<int>>(() => new List<int>().AsQueryable()); } } 公共
public class MyController : ApiController
{
public async Task<IQueryable<int>> Get()
{
return await new Task<IQueryable<int>>(() => new List<int>().AsQueryable());
}
}
公共类MyController:ApiController
{
公共异步任务Get()
{
返回等待新任务(()=>newlist().AsQueryable());
}
}
但这种方法效果很好:
public IQueryable<int> Get()
{
return new List<int>().AsQueryable();
}
public IQueryable Get()
{
返回新列表().AsQueryable();
}
我缺少什么基础知识 你并没有真正开始你的
任务,所以它会等待一些永远不会开始的事情
而是使用Task.Factory.StartNew
,它将同时创建和启动,或者调用Task#start
并等待该调用
启动任务的方法概述:您实际上并没有启动任务,因此它将等待一些永远不会开始的事情
而是使用Task.Factory.StartNew
,它将同时创建和启动,或者调用Task#start
并等待该调用
启动任务的方法概述:如另一个答案所述,控制器未完成的原因是任务未启动。但是,在ASP.NET上使用Task.Start
、Task.Factory.StartNew
或Task.Run
并不是一个好的解决方案
在ASP.NET上使用async
/await
的整个要点就是释放线程。但是,如果您等待通过Start
/StartNew
/Run
启动的任务,那么您将通过从同一线程池中占用另一个线程来释放一个线程。在这种情况下,您不仅失去了async
/await
的所有好处,而且还通过定期抛出ASP.NET线程池试探法,降低了可伸缩性
正如我在博客中所描述的,有两种任务:委托任务(代表线程上执行的一些工作)和承诺任务(代表事件)。您应该避免在ASP.NET上委派任务,包括任何“已启动”的任务(Start
/StartNew
/Run
)
由于您返回的是一个IQueryable
,因此我假设您的实际底层操作是一个数据库查询。如果您使用的是EF6,那么您将获得对的完全支持,这是通过Promise任务正确实现的。正如另一个答案所指出的,控制器未完成的原因是任务未启动。但是,在ASP.NET上使用Task.Start
、Task.Factory.StartNew
或Task.Run
并不是一个好的解决方案
在ASP.NET上使用async
/await
的整个要点就是释放线程。但是,如果您等待通过Start
/StartNew
/Run
启动的任务,那么您将通过从同一线程池中占用另一个线程来释放一个线程。在这种情况下,您不仅失去了async
/await
的所有好处,而且还通过定期抛出ASP.NET线程池试探法,降低了可伸缩性
正如我在博客中所描述的,有两种任务:委托任务(代表线程上执行的一些工作)和承诺任务(代表事件)。您应该避免在ASP.NET上委派任务,包括任何“已启动”的任务(Start
/StartNew
/Run
)
由于您返回的是一个IQueryable
,因此我假设您的实际底层操作是一个数据库查询。如果您使用的是EF6,那么您将获得对的完全支持,这是通过Promise任务正确实现的。绝对不需要使用async
/await
在这里,方法可以如下所示:
public Task<IQueryable<int>> Get()
{
return Task.FromResult(new List<int>().AsQueryable());
}
这将引入很少的开销(编译器将生成一个完整的状态机)
另外,正如其他人已经指出的,从async
方法返回的任务应该是hot(已启动)
请记住,Task.FromResult
将返回已完成的任务,这种情况可以通过async/await
生成的代码进行优化,写入Task.Run
在这种情况下至少是wierd
阅读了解更多详细信息绝对不需要在async
/wait
中,方法可以如下所示:
public Task<IQueryable<int>> Get()
{
return Task.FromResult(new List<int>().AsQueryable());
}
这将引入很少的开销(编译器将生成一个完整的状态机)
另外,正如其他人已经指出的,从async
方法返回的任务应该是hot(已启动)
请记住,Task.FromResult
将返回已完成的任务,这种情况可以通过async/await
生成的代码进行优化,写入Task.Run
在这种情况下至少是wierd
阅读了解更多详细信息当然,有很多不同的方法来启动任务。它们的效果可能稍有不同,具体取决于您所做的操作,但在这里这样一个简单的示例中,无论哪种方式都应该是好的。最重要的一点是实际开始任务。Doh!谢谢我误解了Wait,我认为它也确保了任务的顺利进行。@Chris:你应该接受Stephen的答案,而不是我的,这样更好。@Jeroenvanevel说得对,我同意这是一个更好的答案,但你解决了我最初的愚蠢问题,所以再次感谢你。当然,有很多不同的方法可以开始任务。它们的效果可能稍有不同,具体取决于您所做的操作,但在这里这样一个简单的示例中,无论哪种方式都应该是好的。最重要的一点是实际开始任务。Doh!谢谢我误解了Wait,我认为它也确保了任务的顺利进行。@Chris:你应该接受Stephen的答案,而不是我的,这样更好。@Jeroenvanevel说得对,我同意这是一个更好的答案,但你解决了我最初的愚蠢问题,再次感谢你。