C# IHttpActionResult.ExecuteAsync()重载返回的任务未运行
我正在尝试创建一个自托管Web服务,该服务通过C# IHttpActionResult.ExecuteAsync()重载返回的任务未运行,c#,owin,webapi2,self-host-webapi,C#,Owin,Webapi2,Self Host Webapi,我正在尝试创建一个自托管Web服务,该服务通过Microsoft.Owin.Hosting.WebApp.Start(“http://localhost:9000/“并包含从System.Net.Http.ApicController派生的控制器通知启动如下所示: using System.Web.Http; using Owin; ... class NotifyStartup { public void Configuration(IAppBuilder appBuilder)
Microsoft.Owin.Hosting.WebApp.Start(“http://localhost:9000/“
并包含从System.Net.Http.ApicController
派生的控制器<代码>通知启动如下所示:
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);
}
}
运行该包装器任务,客户端接收其响应
据我所知,由newtask…
和Task.FromResult()
创建的任务应该与调用者看起来相同。为什么它要等待一个而不是另一个呢?我做错了什么?有可能做到这一点吗
由newtask
和Task.FromResult()创建的任务应如下所示
与来电者相同
从调用方的角度来看,它们看起来是相同的,但从实现的角度来看,它们是不同的
任务
构造函数不会启动任务,因此不应该使用它。使用Task.Run
返回热任务:
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);
}
公共任务执行同步(CancellationToken CancellationToken)
{
返回任务。运行(()=>
{
var rspContent=“这是一个响应字符串”;
var rsp=新的HttpResponseMessage(System.Net.HttpStatusCode.OK);
如果(!string.IsNullOrEmpty(rspContent))
{
rsp.Content=新的StringContent(rspContent);
}
返回rsp;
},取消令牌);
}
虽然我认为这本身可能是多余的,但由于WebAPI中的操作本身已经在线程池线程上运行,因此将其包装在附加线程中通常是多余的
由newtask
和Task.FromResult()创建的任务应如下所示
与来电者相同
从调用方的角度来看,它们看起来是相同的,但从实现的角度来看,它们是不同的
任务
构造函数不会启动任务,因此不应该使用它。使用Task.Run
返回热任务:
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);
}
公共任务执行同步(CancellationToken CancellationToken)
{
返回任务。运行(()=>
{
var rspContent=“这是一个响应字符串”;
var rsp=新的HttpResponseMessage(System.Net.HttpStatusCode.OK);
如果(!string.IsNullOrEmpty(rspContent))
{
rsp.Content=新的StringContent(rspContent);
}
返回rsp;
},取消令牌);
}
虽然我认为这本身可能是多余的,但由于WebAPI中的某个操作本身已经在线程池线程上运行,因此通常将其包装在其他线程中是多余的。有些事情我不知道,有些事情我不知道,还有另一个不喜欢.NET的原因。来自C++的我假设任务在哪里和何时运行,直到运行时,调用它的结果足以保证它将同步运行或异步运行。考虑到我在这里唯一的选择是在线程池中显式地调度它,如果可能的话,我最好确保我进行的所有I/O绑定调用都是异步的,并且放弃创建一个实际的、线程可运行的任务。@EvanBurkitt如果您的操作是IO绑定的,那么您根本不需要使用
task.Run
,您需要查看并利用API本身公开异步端点,例如用于进行异步HTTP调用的HttpClient
。是的,这就是我的意思。我应该调用wait
异步函数,而不是创建任务。C#中的异步编程似乎是低级(必须明确决定任务的运行方式和时间)和高级(由wait
操作符创建的神奇延续)的奇怪混合。我不确定我是否喜欢,但我会习惯的。谢谢你的帮助。有些事情我不知道,还有另一个不喜欢.NET的原因。来自C++的我假设任务在哪里和何时运行,直到运行时,调用它的结果足以保证它将同步运行或异步运行。考虑到我在这里唯一的选择是在线程池中显式地调度它,如果可能的话,我最好确保我进行的所有I/O绑定调用都是异步的,并且放弃创建一个实际的、线程可运行的任务。@EvanBurkitt如果您的操作是IO绑定的,那么您根本不需要使用task.Run
,您需要查看并利用API本身公开异步端点,例如用于进行异步HTTP调用的HttpClient
。是的,这就是我的意思。我应该调用wait
异步函数,而不是创建任务。C#中的异步编程似乎是低级(必须明确决定任务的运行方式和时间)和高级(由wait
操作符创建的神奇延续)的奇怪混合。我不确定我是否喜欢,但我会习惯的。我感谢你的帮助。