私は私のasp.net MVC 4アプリケーションで優れたダウンロードをしています。エクスポートボタンをクリックすると、以下のコントローラメソッドが呼び出されます。非同期にする必要があるので、asyncを使用してここで待ちます。
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をinturnで呼び出します。
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;
}
しかし、Warningという警告メッセージが出ます。
この非同期メソッドには 'await'演算子がなく、同期的に実行されます。 ノンブロッキングAPI呼び出しを待つために 'await'演算子を使うことを検討してください。 バックグラウンドスレッドでCPUバウンドの作業を行う場合は、 'Task.Run(...)'を待つ
。私は何か悪いことをしていますか?私のコードはうまく動き、私はExcelをダウンロードすることができます。
私は何か悪いことをしていますか?
まあ、あなたは本当に非同期的に何かをしているのではありません。きみのReportExcelAsync
それは持っていないので、メソッドは完全に同期ですawait
式そうGenerateReportExcel
電話しますReportExcelAsync
これは同期的に実行され、その後完了したタスクを返します。現時点で行ったことは、実装に使用されるステートマシンなどを作成するためのわずかなオーバーヘッドを追加することだけです。async
/await
。
なぜそれが実際に非同期で起こると予想したのかは明確ではありませんが、待機/非同期が実際に何をするのかの誤解だと思います。それしない自動的に新しいスレッドを起動します。非同期APIを作成して使用するのがはるかに簡単になります。
今1つのオプションは単に変更したいということですReportExcelAsync
同期メソッドにReportExcel
を返すstring
)と呼び出しコードでそのための新しいタスクを作成します。
var filePath = await Task.Run(excel.ReportExcel);
しかし、これが実際に多くの利益をもたらすことは明らかではありません。あなたはWebアプリを書いているので、レスポンスがこのように早く配信されるわけではありません - あなたは事実上単にシフト作業が行われているスレッド
あなたは言う:
非同期にする必要があるので
...でも理由はありませんなぜそれは非同期的に行われる必要があります。この場合の同期アプローチの何が問題になっていますか?非同期性は適切な場合には素晴らしいですが、あなたの場合ではないと思います。
ReportExcelAsync
本当に非同期でした - しかしそうではありません。これは警告を生成するメソッドです。await
式 - Jon Skeet