2017-01-24 11 views
1

Microsoft.Owin.Hosting.WebApp.Start<NotifyStartup>("http://localhost:9000/")으로 서버를 시작하고 System.Net.Http.ApiController에서 파생 된 컨트롤러가 포함 된 자체 호스팅 웹 서비스를 만들려고합니다. NotifyStartup은 다음과 같습니다작업이 IHttpActionResult.ExecuteAsync() 오버로드가 실행되지 않음으로 반환했습니다.

using System.Web.Http; 
... 
[Route("notify")] 
[HttpPost] 
public IHttpActionResult Notify([FromBody]object body) 
{ 
    return new HttpAction(); 
} 

여기 HttpAction입니다 :

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.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); 
    } 
} 

(어떤 시점에서 HttpActionNotify()body 매개 변수에주의를 지불한다 rspContent에는 데이터베이스 조회가 필요한 항목이 할당됩니다. 이 작업을 비동기 적으로 수행 할 수 있습니다.)

http://localhost:9000/notify/으로 프로그램을 실행하면 URI 처리기가 호출되고 HttpAction 인스턴스가 생성되고 해당 인스턴스의 ExecuteAsync() 메서드가 호출됩니다. 그러나 반환하는 작업은 절대로 실행되지 않으며 클라이언트는 응답을 기다리면서 중단됩니다. 내가 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 (또는 결과를 얻기 위해 실제로 무엇을 하든지간에) 하나가 아닌 다른 것입니까? 내가 도대체 ​​뭘 잘못하고있는 겁니까? 이 작품을 만들 수 있습니까? new Task<>Task.FromResult() 만든

답변

0

작업은 호출자에게 동일 보일 것입니다.

이들은 호출자 관점에서 동일하게 보이지만 구현 관점에서는 동일하지 않습니다.

Task 생성자는 작업을 시작하지 않으므로 사용하지 않아야합니다. 나는 그 자체로 WebAPI에서 작업이 이미 스레드 풀 스레드에서 실행되기 때문에이 자체로 중복 될 수 있다고 주장 거라고하지만

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); 
} 

, 그것은에 일반적으로 중복 대신 뜨거운 작업을 반환 Task.Run를 사용 추가 스레드 내부를 감싸십시오.

+0

내가 모르는 것을 모르는 뭔가가 있고. NET을 좋아하지 않는 또 다른 이유가 있습니다. C++에서 나는 작업 (미래)이 실행되는 곳과 시점이 런타임까지이며, 그 결과를 요구하는 것이 동기식 또는 비동기식으로 실행될 수 있다고 생각했습니다. 나의 유일한 선택은 스레드 풀에 명시 적으로 스케쥴하는 것입니다. 가능한 경우, 가능한 모든 I/O 바인딩 호출을 비동기 적으로 수행하고 실제 스레드 실행 가능 파일을 작성하는 것이 좋습니다. 태스크. –

+0

@EvanBurkitt 작업이 IO 바운드 인 경우, 'Task.Run'을 전혀 사용할 필요가 없으며 [async-await] (https://msdn.microsoft.com/en-kr) us/library/mt674882.aspx) 비동기 HTTP 호출을하기위한'HttpClient'와 같은 비동기 끝점을 자체적으로 노출하는 API를 활용하십시오. –

+0

그래, 그게 내가 의미하는 바야. 나는 태스크를 생성하는 대신 비동기 함수에'await' 호출을해야한다. C#의 비동기 프로그래밍은 낮은 수준 (작업 실행 방법 및시기를 명시 적으로 결정해야 함)과 높은 수준 ('await'연산자로 만든 마법 지속)의 이상한 혼합 인 것으로 보입니다. 나는 그것을 좋아하는지 모르겠다. 그러나 나는 그것에 익숙해 질 것이다. 도와 주셔서 감사합니다. –