web-dev-qa-db-ja.com

await演算子がないことを示す非同期メソッドの警告メッセージ

Asp.net mvc 4アプリケーションでExcelをダウンロードしています。エクスポートボタンをクリックすると、以下のコントローラーメソッドが呼び出されます。非同期で行う必要があるため、ここでは非同期を使用して待機しています。

public async Task<ActionResult> GenerateReportExcel()
    {
        ExcelGenerator Excel = new ExcelGenerator();
        var filePath = await Excel.ReportExcelAsync(midyearReportViewModel);
        System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
        response.ClearContent();
        response.Clear();
        response.ContentType = "text/plain";
        response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.xlsx;", PdaResource.ReportFileName)); 
        response.TransmitFile(filePath);
        response.Flush();
        response.End();
        return PartialView("_MidYearReportPartial", midyearReportViewModel);
    }

このメソッドは、次に示すように、ExcelジェネレーターメソッドReportExcelAsyncを呼び出します。

public async Task<string> ReportExcelAsync(MidYearReportViewModel _midyearAnnualviewModel)
    {
        string fileName = "MidYearReport";
        string finalXcelPath = string.Empty;
        string currentDirectorypath = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/Export")).ToString();
        finalXcelPath = string.Format("{0}\\{1}.xlsx", currentDirectorypath, fileName);
        if (System.IO.File.Exists(finalXcelPath))
        {
            System.IO.File.Delete(finalXcelPath);
        }
        var newFile = new FileInfo(finalXcelPath);
        using (ResXResourceSet resxSet = new ResXResourceSet(resxFile))
        {
            using (var package = new ExcelPackage(newFile))
            {
                ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(resxSet.GetString("ReportMYMidYearExcelSheetName"));
                for (int i = 1; i <= header.Count(); i++)
                {
                    worksheet.Cells[1, i].Value = header[i - 1];
                    worksheet.Cells[1, i].Style.Font.Bold = true;
                    worksheet.Cells[1, i].Style.Fill.PatternType = ExcelFillStyle.Solid;
                    worksheet.Cells[1, i].Style.Font.Color.SetColor(Color.White);
                    worksheet.Cells[1, i].Style.Fill.BackgroundColor.SetColor(Color.DimGray);
                }
                package.Save();
            }
        }
        return finalXcelPath; 
    }

しかし、警告として警告メッセージが表示されます

この非同期メソッドには「待機」演算子がなく、同期的に実行されます。 'await'演算子を使用して非ブロッキングAPI呼び出しを待機するか、 'await Task.Run(...)'を使用してバックグラウンドスレッドでCPUにバインドされた作業を行うことを検討してください

。私は何か間違ったことをしていますか?.

32
Jayason

私は何か間違ったことをしていますか?

まあ、あなたは本当に非同期で何もしていません。 ReportExcelAsyncメソッドはawait式を持たないため、完全に同期的です。したがって、GenerateReportExcelReportExcelAsyncを呼び出します。これは同期的に実行され、完了したタスクを返します。現時点で行ったことは、async/awaitを実装するために使用されるステートマシンなどを作成するための少量のオーバーヘッドを追加することだけです。

なぜ実際に非同期で起こると思ったのかは明確ではありませんが、await/asyncが実際に行うことの誤解だと思います。 does n't新しいスレッドを自動的に起動します-非同期APIの作成と使用がはるかに簡単になります。

1つのオプションは、ReportExcelAsyncを同期メソッド(ReportExcelstringを返す)に変更し、呼び出しコードでそのための新しいタスクを作成することです。

var filePath = await Task.Run(Excel.ReportExcel);

しかし、これが実際に多くの利益をもたらすかどうかは明らかではありません。あなたはウェブアプリを書いているので、この方法で応答がより速く配信されるようになるわけではありません-あなたは効果的にshifting作業が行われるスレッドです。

あなたは言う:

非同期で行う必要があるので

...しかし、理由はありませんwhy非同期に行う必要があります。この場合の同期アプローチの何が問題になっていますか?非同期性は適切な場合に優れていますが、あなたの場合はそうではないと思います。

63
Jon Skeet