Async Return Types (Visual Basic)
Async methods have three possible return types: Task<TResult>, Task, and void. In Visual Basic, the void return type is written as a Sub procedure. For more information about async methods, see Asynchronous Programming with Async and Await (Visual Basic).
Each return type is examined in one of the following sections, and you can find a full example that uses all three types at the end of the topic.
Note
To run the example, you must have Visual Studio 2012 or newer and the .NET Framework 4.5 or newer installed on your computer.
Task(T) Return Type
The Task<TResult> return type is used for an async method that contains a Return statement in which the operand has type TResult
.
In the following example, the TaskOfT_MethodAsync
async method contains a return statement that returns an integer. Therefore, the method declaration must specify a return type of Task(Of Integer)
.
' TASK(OF T) EXAMPLE
Async Function TaskOfT_MethodAsync() As Task(Of Integer)
' The body of an async method is expected to contain an awaited
' asynchronous call.
' Task.FromResult is a placeholder for actual work that returns a string.
Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())
' The method then can process the result in some way.
Dim leisureHours As Integer
If today.First() = "S" Then
leisureHours = 16
Else
leisureHours = 5
End If
' Because the return statement specifies an operand of type Integer, the
' method must have a return type of Task(Of Integer).
Return leisureHours
End Function
When TaskOfT_MethodAsync
is called from within an await expression, the await expression retrieves the integer value (the value of leisureHours
) that's stored in the task that's returned by TaskOfT_MethodAsync
. For more information about await expressions, see Await Operator.
The following code calls and awaits method TaskOfT_MethodAsync
. The result is assigned to the result1
variable.
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
You can better understand how this happens by separating the call to TaskOfT_MethodAsync
from the application of Await
, as the following code shows. A call to method TaskOfT_MethodAsync
that isn't immediately awaited returns a Task(Of Integer)
, as you would expect from the declaration of the method. The task is assigned to the integerTask
variable in the example. Because integerTask
is a Task<TResult>, it contains a Result property of type TResult
. In this case, TResult represents an integer type. When Await
is applied to integerTask
, the await expression evaluates to the contents of the Result property of integerTask
. The value is assigned to the result2
variable.
Warning
The Result property is a blocking property. If you try to access it before its task is finished, the thread that's currently active is blocked until the task completes and the value is available. In most cases, you should access the value by using Await
instead of accessing the property directly.
' Call and await in separate statements.
Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()
' You can do other work that does not rely on resultTask before awaiting.
textBox1.Text &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf
Dim result2 As Integer = Await integerTask
The display statements in the following code verify that the values of the result1
variable, the result2
variable, and the Result
property are the same. Remember that the Result
property is a blocking property and shouldn't be accessed before its task has been awaited.
' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= vbCrLf & $"Value of result1 variable: {result1}" & vbCrLf
textBox1.Text &= $"Value of result2 variable: {result2}" & vbCrLf
textBox1.Text &= $"Value of resultTask.Result: {integerTask.Result}" & vbCrLf
Task Return Type
Async methods that don't contain a return statement or that contain a return statement that doesn't return an operand usually have a return type of Task. Such methods would be Sub procedures if they were written to run synchronously. If you use a Task
return type for an async method, a calling method can use an Await
operator to suspend the caller's completion until the called async method has finished.
In the following example, async method Task_MethodAsync
doesn't contain a return statement. Therefore, you specify a return type of Task
for the method, which enables Task_MethodAsync
to be awaited. The definition of the Task
type doesn't include a Result
property to store a return value.
' TASK EXAMPLE
Async Function Task_MethodAsync() As Task
' The body of an async method is expected to contain an awaited
' asynchronous call.
' Task.Delay is a placeholder for actual work.
Await Task.Delay(2000)
textBox1.Text &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf
' This method has no return statement, so its return type is Task.
End Function
Task_MethodAsync
is called and awaited by using an await statement instead of an await expression, similar to the calling statement for a synchronous Sub
or void-returning method. The application of an Await
operator in this case doesn't produce a value.
The following code calls and awaits method Task_MethodAsync
.
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
As in the previous Task<TResult> example, you can separate the call to Task_MethodAsync
from the application of an Await
operator, as the following code shows. However, remember that a Task
doesn't have a Result
property, and that no value is produced when an await operator is applied to a Task
.
The following code separates calling Task_MethodAsync
from awaiting the task that Task_MethodAsync
returns.
' Call and await in separate statements.
Dim simpleTask As Task = Task_MethodAsync()
' You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf
Await simpleTask
Void Return Type
The primary use of Sub
procedures is in event handlers, where there is no return type (referred to as a void return type in other languages). A void return also can be used to override void-returning methods or for methods that perform activities that can be categorized as "fire and forget." However, you should return a Task
wherever possible, because a void-returning async method can't be awaited. Any caller of such a method must be able to continue to completion without waiting for the called async method to finish, and the caller must be independent of any values or exceptions that the async method generates.
The caller of a void-returning async method can't catch exceptions that are thrown from the method, and such unhandled exceptions are likely to cause your application to fail. If an exception occurs in an async method that returns a Task or Task<TResult>, the exception is stored in the returned task, and rethrown when the task is awaited. Therefore, make sure that any async method that can produce an exception has a return type of Task or Task<TResult> and that calls to the method are awaited.
For more information about how to catch exceptions in async methods, see Try...Catch...Finally Statement.
The following code defines an async event handler.
' SUB EXAMPLE
Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click
textBox1.Clear()
' Start the process and await its completion. DriverAsync is a
' Task-returning async method.
Await DriverAsync()
' Say goodbye.
textBox1.Text &= vbCrLf & "All done, exiting button-click event handler."
End Sub
Complete Example
The following Windows Presentation Foundation (WPF) project contains the code examples from this topic.
To run the project, perform the following steps:
Start Visual Studio.
On the menu bar, choose File, New, Project.
The New Project dialog box opens.
In the Installed, Templates category, choose Visual Basic, and then choose Windows. Choose WPF Application from the list of project types.
Enter
AsyncReturnTypes
as the name of the project, and then choose the OK button.The new project appears in Solution Explorer.
In the Visual Studio Code Editor, choose the MainWindow.xaml tab.
If the tab is not visible, open the shortcut menu for MainWindow.xaml in Solution Explorer, and then choose Open.
In the XAML window of MainWindow.xaml, replace the code with the following code.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button x:Name="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/> <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/> </Grid> </Window>
A simple window that contains a text box and a button appears in the Design window of MainWindow.xaml.
In Solution Explorer, open the shortcut menu for MainWindow.xaml.vb, and then choose View Code.
Replace the code in MainWindow.xaml.vb with the following code.
Class MainWindow ' SUB EXAMPLE Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click textBox1.Clear() ' Start the process and await its completion. DriverAsync is a ' Task-returning async method. Await DriverAsync() ' Say goodbye. textBox1.Text &= vbCrLf & "All done, exiting button-click event handler." End Sub Async Function DriverAsync() As Task ' Task(Of T) ' Call and await the Task(Of T)-returning async method in the same statement. Dim result1 As Integer = Await TaskOfT_MethodAsync() ' Call and await in separate statements. Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync() ' You can do other work that does not rely on resultTask before awaiting. textBox1.Text &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf Dim result2 As Integer = Await integerTask ' Display the values of the result1 variable, the result2 variable, and ' the resultTask.Result property. textBox1.Text &= vbCrLf & $"Value of result1 variable: {result1}" & vbCrLf textBox1.Text &= $"Value of result2 variable: {result2}" & vbCrLf textBox1.Text &= $"Value of resultTask.Result: {integerTask.Result}" & vbCrLf ' Task ' Call and await the Task-returning async method in the same statement. Await Task_MethodAsync() ' Call and await in separate statements. Dim simpleTask As Task = Task_MethodAsync() ' You can do other work that does not rely on simpleTask before awaiting. textBox1.Text &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf Await simpleTask End Function ' TASK(OF T) EXAMPLE Async Function TaskOfT_MethodAsync() As Task(Of Integer) ' The body of an async method is expected to contain an awaited ' asynchronous call. ' Task.FromResult is a placeholder for actual work that returns a string. Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString()) ' The method then can process the result in some way. Dim leisureHours As Integer If today.First() = "S" Then leisureHours = 16 Else leisureHours = 5 End If ' Because the return statement specifies an operand of type Integer, the ' method must have a return type of Task(Of Integer). Return leisureHours End Function ' TASK EXAMPLE Async Function Task_MethodAsync() As Task ' The body of an async method is expected to contain an awaited ' asynchronous call. ' Task.Delay is a placeholder for actual work. Await Task.Delay(2000) textBox1.Text &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf ' This method has no return statement, so its return type is Task. End Function End Class
Choose the F5 key to run the program, and then choose the Start button.
The following output should appear:
Application can continue working while the Task<T> runs. . . . Value of result1 variable: 5 Value of result2 variable: 5 Value of integerTask.Result: 5 Sorry for the delay. . . . Application can continue working while the Task runs. . . . Sorry for the delay. . . . All done, exiting button-click event handler.
See also
Povratne informacije
https://aka.ms/ContentUserFeedback.
Stiže uskoro: Tijekom 2024. postupno ćemo ukinuti servis Problemi sa servisom GitHub kao mehanizam za povratne informacije za sadržaj i zamijeniti ga novim sustavom za povratne informacije. Dodatne informacije potražite u članku:Pošaljite i pogledajte povratne informacije za