Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步控制器方法不返回_C#_Asp.net_Asp.net Web Api_Async Await - Fatal编程技术网

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说得对,我同意这是一个更好的答案,但你解决了我最初的愚蠢问题,再次感谢你。