IHttpActionResult.ExecuteAsync() 重载返回的任务不是 运行
task returned by IHttpActionResult.ExecuteAsync() overload is not run
我正在尝试创建一个自托管 Web 服务,该服务以 Microsoft.Owin.Hosting.WebApp.Start<NotifyStartup>("http://localhost:9000/")
启动其服务器并包含一个派生自 System.Net.Http.ApiController
的控制器。 NotifyStartup
看起来像这样:
using System.Web.Http;
using Owin;
...
class NotifyStartup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
appBuilder.UseWebApi(config);
}
}
控制器有这个 URI 处理程序:
using System.Web.Http;
...
[Route("notify")]
[HttpPost]
public IHttpActionResult Notify([FromBody]object body)
{
return new HttpAction();
}
这是 HttpAction:
using System.Net.Http;
using System.Web.Http;
using System.Threading;
using System.Threading.Tasks;
...
public class HttpAction : IHttpActionResult
{
public HttpAction() { }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return new Task<HttpResponseMessage>(() =>
{
var rspContent = "here's a response string";
var rsp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
if (!string.IsNullOrEmpty(rspContent))
{
rsp.Content = new StringContent(rspContent);
}
return rsp;
}, cancellationToken);
}
}
(在某些时候 HttpAction
会注意 Notify()
的 body
参数并且 rspContent
会被分配一些需要一些数据库查找的东西,这就是为什么我我正在尝试让这项工作异步进行。)
当我 运行 程序和 POST 到 http://localhost:9000/notify/ 调用 URI 处理程序时,它会创建一个 HttpAction
实例和该实例的 ExecuteAsync()
方法叫做。但是,它 returns 的任务永远不会 运行,并且客户端会挂起等待响应。如果我更改 ExecuteAsync()
以便同步完成工作并在包装器任务中返回响应:
var rspContent = "here's a response string";
var rsp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
if (!string.IsNullOrEmpty(rspContent))
{
rsp.Content = new StringContent(rspContent);
}
return Task.FromResult(rsp);
包装器任务 是 运行 并且客户端收到其响应。
据我所知,new Task<>...
和 Task.FromResult()
创建的任务看起来应该与调用者相同。为什么它会 await
(或者它为获得结果而实际做的任何事情)一个而不是另一个?我究竟做错了什么?有可能使这项工作吗?
the tasks created by new Task<>
and Task.FromResult()
should look
identical to the caller.
从调用者的角度来看,它们看起来确实相同,但从实现的角度来看,它们并不相同。
Task
构造函数不会启动任务,这就是您不应该使用它的原因。而是使用 Task.Run
其中 returns 一个热门任务:
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.Run(() =>
{
var rspContent = "here's a response string";
var rsp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
if (!string.IsNullOrEmpty(rspContent))
{
rsp.Content = new StringContent(rspContent);
}
return rsp;
}, cancellationToken);
}
虽然我认为这本身可能是多余的,因为 WebAPI 中的操作本身已经 运行 在线程池线程上,将它包装在一个额外的线程中通常是多余的.
我正在尝试创建一个自托管 Web 服务,该服务以 Microsoft.Owin.Hosting.WebApp.Start<NotifyStartup>("http://localhost:9000/")
启动其服务器并包含一个派生自 System.Net.Http.ApiController
的控制器。 NotifyStartup
看起来像这样:
using System.Web.Http;
using Owin;
...
class NotifyStartup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
appBuilder.UseWebApi(config);
}
}
控制器有这个 URI 处理程序:
using System.Web.Http;
...
[Route("notify")]
[HttpPost]
public IHttpActionResult Notify([FromBody]object body)
{
return new HttpAction();
}
这是 HttpAction:
using System.Net.Http;
using System.Web.Http;
using System.Threading;
using System.Threading.Tasks;
...
public class HttpAction : IHttpActionResult
{
public HttpAction() { }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return new Task<HttpResponseMessage>(() =>
{
var rspContent = "here's a response string";
var rsp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
if (!string.IsNullOrEmpty(rspContent))
{
rsp.Content = new StringContent(rspContent);
}
return rsp;
}, cancellationToken);
}
}
(在某些时候 HttpAction
会注意 Notify()
的 body
参数并且 rspContent
会被分配一些需要一些数据库查找的东西,这就是为什么我我正在尝试让这项工作异步进行。)
当我 运行 程序和 POST 到 http://localhost:9000/notify/ 调用 URI 处理程序时,它会创建一个 HttpAction
实例和该实例的 ExecuteAsync()
方法叫做。但是,它 returns 的任务永远不会 运行,并且客户端会挂起等待响应。如果我更改 ExecuteAsync()
以便同步完成工作并在包装器任务中返回响应:
var rspContent = "here's a response string";
var rsp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
if (!string.IsNullOrEmpty(rspContent))
{
rsp.Content = new StringContent(rspContent);
}
return Task.FromResult(rsp);
包装器任务 是 运行 并且客户端收到其响应。
据我所知,new Task<>...
和 Task.FromResult()
创建的任务看起来应该与调用者相同。为什么它会 await
(或者它为获得结果而实际做的任何事情)一个而不是另一个?我究竟做错了什么?有可能使这项工作吗?
the tasks created by
new Task<>
andTask.FromResult()
should look identical to the caller.
从调用者的角度来看,它们看起来确实相同,但从实现的角度来看,它们并不相同。
Task
构造函数不会启动任务,这就是您不应该使用它的原因。而是使用 Task.Run
其中 returns 一个热门任务:
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.Run(() =>
{
var rspContent = "here's a response string";
var rsp = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
if (!string.IsNullOrEmpty(rspContent))
{
rsp.Content = new StringContent(rspContent);
}
return rsp;
}, cancellationToken);
}
虽然我认为这本身可能是多余的,因为 WebAPI 中的操作本身已经 运行 在线程池线程上,将它包装在一个额外的线程中通常是多余的.