Asynchronous Programming
30.1 Async/Await Basics
Imports System.Net.Http
Public Async Function DownloadPageAsync(url As String) As Task(Of Integer)
Using client As New HttpClient()
Dim content As String = Await client.GetStringAsync(url)
Return content.Length
End Using
End Function
Public Async Function MainAsync() As Task
Dim length = Await DownloadPageAsync("https://learn.microsoft.com")
Console.WriteLine($"Downloaded {length} chars")
End Function
Sub Main()
MainAsync().GetAwaiter().GetResult() ' VB doesn't support Async Sub Main, so block at the entry point
End Sub30.2 Return Types
Async operation with no result Async operation returning T Only for event handlers (exceptions can't be awaited) ValueTask(Of T) High-performance scenarios (consume)
30.3 Running Tasks Concurrently
Async Function ProcessAllAsync() As Task
Dim urls = {"https://example.com", "https://dotnet.microsoft.com", "https://github.com"}
Dim tasks = urls.Select(Function(u) DownloadPageAsync(u)).ToList()
Dim results As Integer() = Await Task.WhenAll(tasks) ' wait for all
Console.WriteLine($"Total: {results.Sum()}")
Dim first = Await Task.WhenAny(tasks) ' first completed
Await Task.Delay(500) ' non-blocking delay
Dim cpuResult = Await Task.Run(Function() HeavyComputation()) ' offload CPU work to the thread pool
End Function30.4 Cancellation and Progress
Async Function LongOperationAsync(progress As IProgress(Of Integer), token As Threading.CancellationToken) As Task
For i = 1 To 100
token.ThrowIfCancellationRequested()
Await Task.Delay(50, token)
progress?.Report(i)
Next
End Function
Dim cts As New Threading.CancellationTokenSource(TimeSpan.FromSeconds(10))
Dim prog As New Progress(Of Integer)(Sub(p) Console.Write($"{p}% "))
Try
Await LongOperationAsync(prog, cts.Token)
Catch ex As OperationCanceledException
Console.WriteLine("Cancelled.")
End Try
' cts.Cancel() from a button handler, etc.30.5 Async in UI Apps
Private Async Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
btnLoad.Enabled = False
Try
lblStatus.Text = "Loading..."
Dim data = Await Task.Run(Function() LoadDataFromDisk()) ' the UI stays responsive
dgvData.DataSource = data ' back on the UI thread automatically
lblStatus.Text = "Done"
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
btnLoad.Enabled = True
End Try
End Sub30.6 Async Best Practices
"Async all the way": avoid .Result / .Wait() in UI or ASP.NET code (they cause deadlocks).
Use ConfigureAwait(False) in library code. Avoid Async Sub except for event handlers.
Name async methods with an Async suffix. Pass CancellationTokens through.