I have a excel download in my asp.net mvc 4 application. When I click the export button the below controller method gets called. Since I need it to be done asynchronous, I am using async and await here.
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);
}
This method inturn call a excel generator method ReportExcelAsync as shown below
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;
}
But I get a warning message as Warning
This async method lacks 'await' operators and will run synchronously.
Consider using the 'await' operator to await non-blocking API calls,
or 'await Task.Run(…)' to do CPU-bound work on a background thread
. Am I doing something wrong ?.My code works fine and I am able to get the excel downloaded.
Best Answer
Well, you're not really doing anything asynchronously. Your
ReportExcelAsync
method is entirely synchronous, as it doesn't have anyawait
expressions. SoGenerateReportExcel
will callReportExcelAsync
, which will run synchronously, and then return a completed task. All you've done at the moment is add a small amount of overhead for creating the state machine etc that is used to implementasync
/await
.It's not clear why you expected it to actually happen asynchronously, but I suspect it's a misunderstanding of what await/async actually does. It doesn't start up new threads for you automatically - it just makes it much easier to create and consume asynchronous APIs.
Now one option is to just want to change
ReportExcelAsync
into a synchronous method (ReportExcel
, returning astring
) and create a new task for that in the calling code:However, it's not clear that this would actually give you much benefit. You're writing a web app, so it's not like the response is going to be delivered any faster this way - you're effectively just shifting the thread the work is done on.
You say:
... but give no reasons why it needs to be done asynchronously. What's wrong with the synchronous approach in this case? Asynchrony is great when it's appropriate, but I don't think it is in your case.