web-dev-qa-db-ja.com

非同期Task <IHttpActionResult>を使用したWeb API 2ダウンロードファイル

テキストドキュメント(.txt、pdf、.doc、.docxなど)を返すために以下のようなメソッドを記述する必要があります。Web上のWeb API 2.0に投稿ファイルの良い例がありますが、関連するものが見つかりませんでしたダウンロードするだけです。 (HttpResponseMessageでそれを行う方法を知っています。)

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

上記はまったく非同期である必要がありますか?ストリームを返すだけです。 (それは大丈夫ですか?)

より重要なこと何らかの方法で仕事をする前に、私はこの種の仕事を行う「正しい」方法は何かを知りたいと思っていました...非常に感謝します)..ありがとう。

20
Kcats Wolfrevo

確かに、上記のシナリオでは、アクションはasyncアクションの結果を返す必要はありません。ここでは、カスタム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);
    }
}
37
Kiran Challa

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 replacesがContinueWithを「同期」コードに展開することです。

コントローラーメソッドからタスクを返すwhat IO(私が推定するケースの99%)は、ランタイムがIO操作が進行中です。これにより、スレッドプールスレッドが不足する可能性が低くなります。トピックに関する記事を次に示します。 http://www.asp.net/mvc/overview/performance/using-asynchronous -methods-in-aspnet-mvc-4

「上記は非同期である必要がありますか?ストリームを返すだけです。(大丈夫ですか?)」という質問に対する答えは、呼び出し側に違いはなく、コードの見た目を変えるだけです(仕組みではありません)。

3
user3285954