2014-01-23 25 views
27

我在我的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); 
    } 

这种方法inturn调用一个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; 
    } 

但我得到一个警告消息警告

这种异步方法缺乏“等待”运营商和意志同步运行。 考虑使用“等待”操作,以等待非阻塞API调用, 或“伺机Task.Run(...)”做在后台线程

CPU限制的工作。我做错了什么?我的代码工作正常,我可以得到excel下载。

回答

58

我做错了什么?

那么,你并没有真正做任何事情异步。您的ReportExcelAsync方法完全同步,因为它没有任何await表达式。因此GenerateReportExcel将调用ReportExcelAsync,它将同步运行,然后返回一个完成的任务。您目前所做的只是添加一小部分开销来创建用于实现async/await的状态机等。

目前尚不清楚为什么你期望它实际上是异步发生的,但我怀疑这是对等待/异步实际做什么的误解。它不会自动启动新线程 - 它只是使创建和使用异步API更容易。

现在,一种选择是只需要换ReportExcelAsync成同步方法(ReportExcel,返回string),并调用代码创建一个新的任务为:

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

不过,目前尚不清楚,这实际上会给你带来很多好处。你正在编写一个Web应用程序,所以它不会像这样快速地提供响应 - 你只需要即可完成这个工作完成的线程。

你说:

因为我需要它做异步

...但给为什么它需要异步完成任何理由。在这种情况下,同步方法有什么问题?在适当的情况下,异步非常棒,但我认为它不适合您。

+0

是不是这行var filePath = await excel.ReportExcelAsync(midyearReportViewModel);是在做?第二条线。 – stevethethread

+1

@stevethethread:如果* ReportExcelAsync真的是异步的,那将会异步执行*但事实并非如此。这是产生警告的方法,因为它没有“await”表达式。 –

+0

@Skeet我的目标是生成excel并异步返回路径。 – user2988112