I need to make BuildReports() Asynchronous because this Function can take several minutes to complete depending on the number of reports it has to create. It is called by btnClearAll_Click() that I added ‘Async’ and ‘Await’ too. I’ve added ‘Async’ to BuildReports() and tried numerous placements for ‘Await’ including using on the If-Then-Else’ statement prior to the loop. I also tried ‘Awaitable’ for the datatable (dt) created in reportComponent.CreatePDF() (a SQL Select query). ClearAll() is Synchronous.
So I need some help here, I’ve read numerous articles on this but I missing something. Any guidance will be appreciated.
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
The compiler should be giving you an error with that code, because BuildReports
is marked as Async
but is not using Await
.
Note that "asynchronous" does not mean "run on a background thread". Thus, there is no way to "make" synchronous code asynchronous; the code itself is synchronous or asynchronous by nature.
So, for example, if you had naturally-asynchronous database operations (e.g., using Entity Framework), then you could have a naturally-asynchronous BuildReports
. However, the DataTable
API is not amenable to asynchrony, so DataTable
does not have asynchronous APIs at all. It is firmly stuck in the synchronous world.
In your particular case, it's probably best to run your existing synchronous code on a background thread, which can be done with Task.Run
. You can then consume it asynchronously:
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()
...