22

我需要编写如下方法来返回文本文档(.txt、pdf、.doc、.docx 等)虽然有很好的在 Web API 2.0 中发布文件的示例,但我找不到相关的只需下载一个。(我知道如何在 HttpResponseMessage 中做到这一点。)

  public async Task<IHttpActionResult> GetFileAsync(int FileId)
  {    
       //just returning file part (no other logic needed)
  }

以上内容是否需要异步?我只想返回流。(可以吗?)

更重要的是,在我最终以一种或另一种方式完成工作之前,我想知道做这种工作的“正确”方式是什么......(因此,非常感谢提及这一点的方法和技术)......谢谢。

4

2 回答 2

40

对,对于您的上述情况,该操作不需要返回异步操作结果。在这里,我正在创建一个自定义 IHttpActionResult。您可以在下面的代码中查看我的评论。

public IHttpActionResult GetFileAsync(int fileId)
{
    // NOTE: If there was any other 'async' stuff here, then you would need to return
    // a Task<IHttpActionResult>, but for this simple case you need not.

    return new FileActionResult(fileId);
}

public class FileActionResult : IHttpActionResult
{
    public FileActionResult(int fileId)
    {
        this.FileId = fileId;
    }

    public int FileId { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage();
        response.Content = new StreamContent(File.OpenRead(@"<base path>" + FileId));
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

        // NOTE: Here I am just setting the result on the Task and not really doing any async stuff. 
        // But let's say you do stuff like contacting a File hosting service to get the file, then you would do 'async' stuff here.

        return Task.FromResult(response);
    }
}
于 2014-02-06T17:06:22.560 回答
3

如果返回 Task 对象,方法是异步的,而不是因为用 async 关键字修饰。async 只是替换此语法的语法糖,当有更多任务组合或更多延续时,它会变得相当复杂:

public Task<int> ExampleMethodAsync()
{
    var httpClient = new HttpClient();

    var task = httpClient.GetStringAsync("http://msdn.microsoft.com")
        .ContinueWith(previousTask =>
        {
            ResultsTextBox.Text += "Preparing to finish ExampleMethodAsync.\n";

            int exampleInt = previousTask.Result.Length;

            return exampleInt;
        });

    return task;
}

带有异步的原始示例:http: //msdn.microsoft.com/en-us/library/hh156513.aspx

async 总是需要等待,这是由编译器强制执行的。

两种实现都是异步的,唯一的区别是 async+await 替换将 ContinueWith 扩展为“同步”代码。

从控制器方法返回任务 IO 做什么(我估计 99% 的情况)很重要,因为运行时可以在 IO 操作正在进行时暂停并重用请求线程来服务其他请求。这降低了线程池线程用完的机会。这是一篇关于该主题的文章: http ://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4

因此,您的问题“以上内容是否需要异步?我只想返回流。(可以吗?)”的答案是它对调用者没有任何影响,它只会改变您的代码的外观(但不是它是如何工作的)。

于 2015-01-02T22:04:59.193 回答