2016-08-03 2 views
0

이 함수는 작성해야하는 보고서 수에 따라 완료하는 데 몇 분이 걸릴 수 있으므로 BuildReports()를 비동기로 만들어야합니다. btnClearAll_Click()에 의해 호출되어 'Async'및 'Await'도 추가되었습니다. BuildReports()에 'Async'를 추가하고 루프 이전에 If-Then-Else 문을 사용하는 것을 포함하여 'Await'에 대한 수많은 배치를 시도했습니다. 나는 또한 reportComponent.CreatePDF() (SQL Select 쿼리)에서 생성 된 datatable (dt)에 대해 'Awaitable'을 시도했다. ClearAll()은 동기입니다.루프의 작업 기반 비동기 패턴

그래서 나는 여기에 도움이 필요하다. 나는 이것에 관한 수많은 기사를 읽었지만 나는 뭔가를 놓쳤다. 모든 지침을 주시면 감사하겠습니다.

Private Async Sub btnClearAll_Click(sender As Object, e As System.EventArgs) Handles btnClearAll.Click 

    Await BuildReports() 

    ClearAll() 

End Sub 

Private Async Function BuildReports() As Task 

    Try 
     Dim reportComponent As New ReportComponent(CStr(Session("UserConnectionString"))) 
     Dim dt As New DataTable 

     dt = reportComponent.CreatePDF() 

     If dt IsNot Nothing Then 
      Dim ScheduleDto As New ScheduleDto() 
      Dim scheduleDtoList As New List(Of ScheduleDto)() 
      Dim report1 As Telerik.Reporting.Report = Nothing 

      For Each row As DataRow In dt.Rows 
       For i As Integer = 0 To dt.Rows.Count - 1 
        If row IsNot Nothing Then 
         ScheduleDto.Encounter_code = dt.Rows.Item(i).Item("Encounter_code").ToString 
         ScheduleDto.CaseNumber = dt.Rows.Item(i).Item("CaseNumber").ToString 
         ScheduleDto.Case_Name = dt.Rows.Item(i).Item("Case_Name").ToString 
         ScheduleDto.DOS = dt.Rows.Item(i).Item("DOS").ToString 
         ScheduleDto.Provider = dt.Rows.Item(i).Item("Provider").ToString 
         ScheduleDto.Discipline = dt.Rows.Item(i).Item("Discipline").ToString 
         ScheduleDto.Episode = dt.Rows.Item(i).Item("Episode").ToString 
         ScheduleDto.ReportType = dt.Rows.Item(i).Item("ReportType").ToString 
         ScheduleDto.DocumentName = dt.Rows.Item(i).Item("Document_Name").ToString 
         ScheduleDto.ItemType = dt.Rows.Item(i).Item("ItemType").ToString 

         scheduleDtoList.Add(ScheduleDto) 
         report1 = reportComponent.GetReport(ScheduleDto, ScheduleDto.ReportType, CStr(Session("UserConnectionString"))) 
         If (report1 IsNot Nothing) Then 
          Dim pdfPath As String = "" 
          Dim DownloadReport As New DownloadReports() 
         DownloadReport.DownloadReport(report1, ScheduleDto, ScheduleDto.DocumentName, ScheduleDto.ReportType, pdfPath) 
         reportComponent.FinalizeNow(ScheduleDto.Encounter_code) 

         End If 
        End If 
       Next 
      Next 

     Else : Return 
     End If 

    Catch ex As SqlException 
     Throw New Exception(ex.Message & " : Build_Reports") 
    Finally 
    End Try 


End Function 

답변

0

컴파일러는 BuildReportsAsync로 표시되어 있지만 Await를 사용하지 않기 때문에, 그 코드가 포함 된 오류를 제공해야합니다.

"비동기"는 이 아니며은 "백그라운드 스레드에서 실행"을 의미합니다. 따라서 동기 코드를 비동기 적으로 "만드는"방법은 없습니다. 코드 자체는 동 기적 또는 비동기 적입니다.

예를 들어 자연스럽게 비동기 인 데이터베이스 작업 (예 : Entity Framework)이있는 경우 자연스럽게 비동기 인 BuildReports을 가질 수 있습니다. 그러나 DataTable API는 비동기 성을 허용하지 않으므로 DataTable에는 비동기 API가 전혀 없습니다. 그것은 동기 세계에서 단단히 붙어 있습니다.

특정 경우에 Task.Run으로 수행 할 수있는 기존 동기화 코드를 백그라운드 스레드에서 실행하는 것이 가장 좋습니다. 그런 다음 비동기에게 그것을 소비 할 수 있습니다 :

Private Async Sub btnClearAll_Click(sender As Object, e As System.EventArgs) Handles btnClearAll.Click 
    Await Task.Run(Function() BuildReports()) 
    ClearAll() 
End Sub 

Private Sub BuildReports() 
... 
+0

감사 스티븐합니다. 제안 된 변경 사항 만들기 "Expression은 값을 생성하지 않습니다.": Task.Run (Function() BuildReports())을 기다립니다. 어떤 아이디어? – JackW9653

+0

@ JackW9653 : 죄송합니다. 'Function'이 아니라 익명의'Sub'이어야합니다. –

+0

완벽하게 작동합니다! @Stephen에게 감사합니다. 몇 가지 기사를 읽었습니다. 향후 프로젝트에서 Async/Await을 사용하는 것에 대한 좋은 설명을 제안 할 수 있습니까? 도움에 다시 한번 감사드립니다. – JackW9653