2014-01-23 51 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