从async ApiController返回立即响应

tca*_*vin 1 c# task-parallel-library c#-4.0 asp.net-web-api

我遇到了从正常的异步ApiController返回"立即"响应的问题.代码如下,寻找感叹号.用例是内容类型检查失败,我想发回错误响应消息.第一个版本挂起了Visual Studion 2010(和Fiddler).第二部作品.

我的问题是,为什么我不能使用我的初始方法返回仅仅传回响应对象的虚拟任务?

public class MyController : ApiController
{

   public Task<HttpResponseMessage> Post([FromUri]string arg)
   {
       HttpResponseMessage response = null;

       // synchronous validation
       if (Request.Content.Headers.ContentType.MediaType != @"image/jpeg")
       {                    
           response = Request.CreateErrorResponse(
               HttpStatusCode.UnsupportedMediaType,
               "Invalid Content-Type.");
       }


       if (response == null)  // no immediate response, switch to async
       {
          // work done here    
       }
       else // immediate response, but we need to wrap in a task for caller to fetch
       {

           // !!!! this one doesn't work !!!
           return new Task<HttpResponseMessage>( () => response);

           // !!! this one does !!!
           TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
           tcs.SetResult(response); 
           return tcs.Task;

       }
    }
}
Run Code Online (Sandbox Code Playgroud)

svi*_*ick 8

Task<T>返回一个尚未启动的任务的构造函数,为了使其工作,您必须执行以下操作:

var task = new Task<HttpResponseMessage>(() => response);
task.Start();
return task;
Run Code Online (Sandbox Code Playgroud)

但这样做效率很低,因为不必要地在线程池上执行lambda.你的第二个版本更好,在.Net 4.5中可以使用更好的版本Task.FromResult():

return Task.FromResult(response);
Run Code Online (Sandbox Code Playgroud)