Async Return Types (Visual Basic) (Типы возвращаемых значений Async (Visual Basic))
Асинхронные методы имеют три возможных типа возврата: Task<TResult>, Task и void. В Visual Basic тип возвращаемого значения void записывается как процедура Sub. Дополнительные сведения о асинхронном программировании см. в статье "Асинхронное программирование" и "Ожидание" (Visual Basic).
Каждый тип возвращаемого значения рассматривается в одном из следующих разделов, а полный пример, в котором используются все три типа, вы найдете в конце этого раздела.
Примечание.
Для выполнения этого примера на компьютере должны быть установлены Visual Studio 2012 или более поздней версии и .NET Framework 4.5 или более поздней версии.
Тип возвращаемого значения task(T)
Тип Task<TResult> возвращаемого значения используется для асинхронного метода, содержащего оператор Return , в котором операнд имеет тип TResult
.
В следующем примере асинхронный метод TaskOfT_MethodAsync
содержит оператор return, который возвращает целое число. Поэтому в объявлении метода должен указываться тип возвращаемого значения 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
При вызове TaskOfT_MethodAsync
из выражения await это выражение await извлекает целочисленное значение (значение leisureHours
), хранящееся в задаче, которая возвращается TaskOfT_MethodAsync
. Дополнительные сведения о выражениях await см. в разделе "Оператор Await".
В следующем коде вызывается и ожидается метод TaskOfT_MethodAsync
. Результат назначается переменной result1
.
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
Чтобы лучше понять, как это происходит, отделите вызов метода TaskOfT_MethodAsync
от применения Await
, как показано в следующем коде. Вызов метода TaskOfT_MethodAsync
, который не ожидается немедленно, возвращает Task(Of Integer)
, как и следовало ожидать из объявления метода. В данном примере эта задача назначается переменной integerTask
. Поскольку integerTask
является Task<TResult>, она содержит свойство Result типа TResult
. В этом примере TResult представляет собой целочисленный тип. Если выражение Await
применяется к integerTask
, выражение await вычисляется как содержимое свойства Result объекта integerTask
. Это значение присваивается переменной result2
.
Предупреждение
Свойство Result является блокирующим свойством. При попытке доступа к нему до завершения его задачи поток, который в текущий момент активен, блокируется до того момента, пока задача не будет завершена, а ее значение не станет доступным. В большинстве случаев следует получать доступ к этому значению с помощью Await
вместо прямого обращения к свойству.
' 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
Операторы отображения в следующем коде проверяют, одинаковы ли значения переменной result1
, переменной result2
и свойства Result
. Помните, что свойство Result
является блокирующим свойством, и к нему не стоит обращаться до того, как его задача закончит ожидание.
' 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 или содержащие оператор return, который не возвращает операнд, обычно имеют тип возврата Task. Такие методы будут вложенными процедурами, если они были написаны для синхронного выполнения. Если для асинхронного метода вы используете тип возвращаемого значения Task
, вызывающий метод может использовать оператор Await
для приостановки выполнения вызывающего объекта до завершения вызванного асинхронного метода.
В следующем примере асинхронный метод Task_MethodAsync
не содержит оператор return. Следовательно, вы указываете для метода тип возвращаемого значения Task
, который позволяет ожидать Task_MethodAsync
. Определение типа Task
не включает свойство Result
для хранения возвращаемого значения.
' 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
вызывается и ожидается с помощью оператора await (вместо выражения await), похожего на оператор вызова для синхронного метода, возвращающего Sub
или void. Await
Приложение оператора в этом случае не создает значение.
В следующем коде вызывается и ожидается метод Task_MethodAsync
.
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
Как показано в предыдущем Task<TResult> примере, можно разделить вызов Task_MethodAsync
от приложения Await
оператора, как показано в следующем коде. Однако следует помнить, что Task
не содержит свойство Result
, и при применении оператора await к Task
никакое значение не создается.
В следующем коде вызов Task_MethodAsync
отделяется от ожидания задачи, которая возвращает 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
Тип возвращаемого значения Void
Основное использование Sub
процедур — в обработчиках событий, где нет возвращаемого типа (называемого типом возвращаемого значения void на других языках). Возврат void также можно использовать для переопределения методов, возвращающих void, или для методов, выполняющих действия, которые можно классифицировать как "огонь и забыть". Тем не менее, вы должны возвращать Task
везде, где это возможно, так как возвращающий асинхронный метод void не может быть ожидаем. Любой вызывающий объект такого метода должен иметь возможность завершить свою работу, не дожидаясь завершения вызванного асинхронного метода, и он не должен зависеть ни от каких значений и исключений, создаваемых асинхронным методом.
Вызывающий объект асинхронного метода, возвращающего void, не может перехватывать исключения, создаваемые методом, и такие необработанные исключения могут привести к сбою приложения. Если исключение возникает в асинхронном методе, который возвращает Task или Task<TResult>, исключение хранится в возвращенной задаче и повторно вызывается при ожидании задачи. Поэтому убедитесь, что любой асинхронный метод, который может вызвать исключение, имеет тип возвращаемого значения Task или Task<TResult> и что вызовы метода являются ожидаемыми.
Дополнительные сведения о перехвате исключений в асинхронных методах см. в статье об операторе Try...Catch...Finally.
Следующий код определяет асинхронный обработчик событий.
' 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
Полный пример
Следующий проект Windows Presentation Foundation (WPF) содержит примеры кода из этого раздела.
Чтобы запустить проект, выполните следующие действия.
Запустите среду Visual Studio.
В главном меню выберите Файл, Создать, Проект.
Откроется диалоговое окно Создание проекта .
В категории "Установленные", "Шаблоны" выберите Visual Basic и выберите Windows. В списке типов проектов выберите Приложение WPF.
Введите
AsyncReturnTypes
в качестве имени проекта и нажмите кнопку ОК.В обозревателе решений появится новый проект.
В редакторе кода Visual Studio перейдите на вкладку MainWindow.xaml .
Если вкладка не отображается, откройте контекстное меню для MainWindow.xaml в обозревателе решений и выберите пункт Открыть.
В окне XAML MainWindow.xaml замените код на следующий.
<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>
Простое окно, содержащее текстовое поле и кнопку, отобразится в окне конструктора для MainWindow.xaml.
В Обозреватель решений откройте контекстное меню для MainWindow.xaml.vb, а затем выберите "Просмотреть код".
Замените код в MainWindow.xaml.vb на приведенный далее.
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
Нажмите клавишу F5, чтобы запустить программу, а затем нажмите кнопку Start .
Должны появиться следующие выходные данные:
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.
См. также
- FromResult
- Walkthrough: Accessing the Web by Using Async and Await (Visual Basic) (Пошаговое руководство. Доступ к веб-сайтам с помощью модификатора Async и оператора Await (Visual Basic))
- Control Flow in Async Programs (Visual Basic) (Поток управления в асинхронных программах (Visual Basic))
- Асинхронный режим
- Оператор Await
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по