28

내 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);
    }

이 메소드는 아래와 같이 ExcelExcelAsync 생성기 메서드를 호출합니다.

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'연산자가없고 동기식으로 실행됩니다.   'await'연산자를 사용하여 비 차단 API 호출을 기다리는 것이 좋습니다.   또는 'Task.Run (...)'백그라운드 스레드에서 CPU 바운드 작업을 수행하기 위해 기다리고 있습니다.

. 뭔가 잘못하고 있는거야? 내 코드가 제대로 작동하고 다운로드 한 엑셀을 얻을 수있다.

1 답변


59

내가 뭔가 잘못하고 있는거야?

글쎄, 당신은 실제로 비동기 적으로 아무것도하지 않습니다. 너의ReportExcelAsync메소드는 완전히 동기식입니다.await표현. 그래서GenerateReportExcel전화 할 것이다.ReportExcelAsync, 동기식으로 실행 한 다음 완료된 태스크를 리턴합니다. 현재 당신이 수행 한 것은 상태 머신 등을 만들기위한 약간의 오버 헤드를 추가하는 것입니다.async/await.

왜 비동기 적으로 실제로 일어날 것이라고 예상했는지는 명확하지 않지만 실제로 / async가 실제로 기다리는 것이 오해 된 것 같습니다. 그것하지 않는다자동으로 새 스레드를 시작하십시오. 비동기 API를 만들고 사용하는 것이 훨씬 쉬워집니다.

이제는 하나의 옵션으로 변경하고 싶을뿐입니다.ReportExcelAsync동기 방식으로ReportExcel,string) 호출 코드에서 해당 작업을 새로 작성하십시오.

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

그러나 이것이 실제로 많은 이점을 줄 것이라고는 분명하지 않습니다. 웹 앱을 작성하고 있으므로 응답이 이렇게 빨리 전달되지는 않습니다. 사실,이동작업이 끝난 스레드.

너는 이렇게 말한다 :

비동기로 수행해야하므로

...하지만 아무 이유도주지 말라.비동기 적으로 수행되어야합니다. 이 경우 동기식 접근 방식의 문제점은 무엇입니까? 비동기는 적절할 때 좋지만, 나는 그것이 당신의 경우라고 생각하지 않습니다.


  • 이 줄은 var filePath = 기다리고 있지 않습니다 excel.ReportExcelAsync (midyearReportViewModel); 하고있다? 2 라인. - stevethethread
  • @stevethethread : 그건 비동기 적으로 일을하는거야.만약 ReportExcelAsync정말 비동기 적이었습니다 -하지만 그렇지는 않습니다. 경고가 생성되는 방법은 경고를 생성하는 방법입니다.await표현. - Jon Skeet
  • @Skeet 내 목표는 Excel을 생성하고 비동기 적으로 경로를 반환하는 것이 었습니다. - Jayason
  • @ user2988112 : '비동기식으로'라는 단어에 대한 이해가 의심 스럽습니다. 내 것과 같지 않다. 당신이하고있는 모든 것은 동기식입니다 - 비동기가 어디서 들어올 것으로 예상 했습니까? 그리고 당신에게 기대했던 구체적인 이점은 무엇입니까? 뭐문제너 여기서 실제로 해결하려고 노력하고 있니? - Jon Skeet
  • @ user2988112 : 왜? 여전히 많은 작업을해야하며 모든 작업은 로컬에서 수행됩니다. 모든 스레드를 비우는 것이 싫다고합니다. 비동기를 마법의 탄환으로 생각하는 것처럼 느껴집니다. 실제로는 그렇지 않습니다. 실제 비동기가 어디에서 왔는지 생각해야합니다. 예를 들어, 데이터베이스에서 비동기 적으로 데이터를 가져올 수 있거나 필요한 스레드 수를 줄일 수있는 비동기 IO를 수행 할 수있는 경우 - 그렇지 않으면 도움이 될 것이라고 생각하지 않습니다. 너는 실제로있다현재 성능 문제가 있습니까? - Jon Skeet

연결된 질문


관련된 질문

최근 질문