异步返回类型(C# 和 Visual Basic)
异步方法有三个可能返回类型:Task<TResult>、Task和无效。 在 Visual Basic 中,返回类型为 void 编写为 子 程序。 有关异步方法的更多信息,请参见 使用 Async 和 Await 的异步编程(C# 和 Visual Basic)。
每个返回类型在以下某一节中检查,因此,您可以找到使用这三个类型在本主题的末尾列出的完整示例。
备注
若要运行该示例,需要 Visual Studio 2012 中,Visual Studio express 2012 中的 windows 桌面或在您的计算机上安装 .NET framework 4.5。
本主题包括下列各节。
- 任务 (of T) 返回类型
- 任务返回类型
- 返回类型为 void
- 完整的示例
- 相关主题
任务 (of T) 返回类型
Task<TResult> 返回类型为包含一个 返回 的异步方法使用 (Visual Basic) 或 返回 (c#) 语句将操作个线程类型 TResult。
在下面的示例中,TaskOfT_MethodAsync 异步方法返回包含整数的返回语句。 因此,方法声明在 Visual Basic 必须指定 Task(Of Integer) 或 Task<int> 的返回类型在 c# 中。
' 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<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
// The body of the method is expected to contain an awaited asynchronous
// call.
// Task.FromResult is a placeholder for actual work that returns a string.
var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
// The method then can process the result in some way.
int leisureHours;
if (today.First() == 'S')
leisureHours = 16;
else
leisureHours = 5;
// Because the return statement specifies an operand of type int, the
// method must have a return type of Task<int>.
return leisureHours;
}
当 TaskOfT_MethodAsync 调用从等待表达式内时,等待表达式检索在任务存储由 TaskOfT_MethodAsync返回的整数值 ( leisureHours的值)。 有关的更多信息的等待表达式,请参见 Await 运算符 (Visual Basic) 或 await(C# 参考)。
下面的代码调用并等待方法 TaskOfT_MethodAsync。 该结果分配给 result1 变量。
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
// Call and await the Task<T>-returning async method in the same statement.
int result1 = await TaskOfT_MethodAsync();
可以更好地了解了如何通过将发生了调用 TaskOfT_MethodAsync 从 Await 或 await的应用程序,如以下代码所示。 对于不立即等待的方法 TaskOfT_MethodAsync 的调用返回 Task(Of Integer) 或 Task<int>,因为想要方法的说明。 任务分配给该示例中的 integerTask 变量。 由于 integerTask 是 Task<TResult>,它包含类型 TResult一个 Result 属性。 在这种情况下,TResult 表示整数类型。 当 Await 或 await 适用于 integerTask时,等待表达式的计算结果为 integerTaskResult 属性的内容。 该值赋给 result2 变量。
警告
Result 属性是一个块的属性。如果您尝试访问它,请在其任务完成之前,当前处于活动状态的线程阻塞,直至任务完成和值可用。在大多数情况下,您应访问该值使用 Await 或 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 &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf)
Dim result2 As Integer = Await integerTask
// Call and await in separate statements.
Task<int> integerTask = TaskOfT_MethodAsync();
// You can do other work that does not rely on integerTask before awaiting.
textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");
int result2 = await integerTask;
在下面的代码显示了语句验证 result1 变量、result2 变量和 Result 属性的值相同。 确保 Result 属性是一个块的属性,并不应访问,在其任务等待之前。
' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable: {0}" & vbCrLf, result1)
textBox1.Text &= String.Format("Value of result2 variable: {0}" & vbCrLf, result2)
textBox1.Text &= String.Format("Value of resultTask.Result: {0}" & vbCrLf, integerTask.Result)
// Display the values of the result1 variable, the result2 variable, and
// the integerTask.Result property.
textBox1.Text += String.Format("\r\nValue of result1 variable: {0}\r\n", result1);
textBox1.Text += String.Format("Value of result2 variable: {0}\r\n", result2);
textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);
任务返回类型
不包含一个返回语句或包含一个返回语句不返回的操作的异步方法通常具有 Task的一个返回类型。 此类方法将无效返回方法 (在 Visual Basic 中子 程序),则它们编写同步运行。 如果使用 Task 返回异步方法的类型,一个调用的方法可以使用等待运算符挂起调用方的完成,直到调用异步方法完成。
在下面的示例中,异步方法 Task_MethodAsync 不包含一个返回语句。 因此,您为方法指定 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 &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)
' This method has no return statement, so its return type is Task.
End Function
// TASK EXAMPLE
async Task Task_MethodAsync()
{
// 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);
// Task.Delay delays the following line by two seconds.
textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");
// This method has no return statement, so its return type is Task.
}
Task_MethodAsync 调用并等待通过使用等待语句而不是等待表达式,与一个同步 Sub 或无效返回方法中的调用语句。 等待运算符的应用程序在这种情况下不生成值。
下面的代码调用并等待方法 Task_MethodAsync。
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
// Call and await the Task-returning async method in the same statement.
await Task_MethodAsync();
如以下代码所示,以前的 Task<TResult> 示例,可以分隔调用 Task_MethodAsync 从等待运算符的应用程序。 但是,请记住 Task 没有一个 Result 属性,并且,值没有生成,当等待运算符应用于 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 &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf)
Await simpleTask
// Call and await in separate statements.
Task simpleTask = Task_MethodAsync();
// You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");
await simpleTask;
返回类型为 void
为无效的主要用于返回类型 (在 Visual Basic 中Sub 程序) 在事件处理程序,返回类型为 void 需要。 void 返回还可以使用重写 void 返回方法或者实现事件可分类为“忘记失火的方法的”。但是,在中,因为无效返回的异步方法不能等待,应在可能的情况下返回 Task。 此类方法的所有调用方必须能够继续完成,而不等待调用异步方法完成,因此,调用方必须是异步方法生成任何值或异常无关。
无效返回的异步方法的调用方无法捕获从方法,引发的异常,这种未经处理的异常会导致应用程序失败。 如果在返回 Task 或 Task<TResult>的异步方法时,异常在返回的任务和再次存储,当等待任务时。 因此,请确保可能会导致异常的所有异步和对方法等待的方法有 Task 的一个返回类型或 Task<TResult>。
有关如何捕获异步方法的异常的更多信息,请参见 try-catch(C# 参考) 或 Try...Catch...Finally 语句 (Visual Basic)。
下面的代码定义了一个异步事件处理程序。
' 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
// VOID EXAMPLE
private async void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Clear();
// Start the process and await its completion. DriverAsync is a
// Task-returning async method.
await DriverAsync();
// Say goodbye.
textBox1.Text += "\r\nAll done, exiting button-click event handler.";
}
完整的示例
以下 windows 演示基础 (WPF) 项都包含来自此主题的代码示例。
若要运行项目,请执行以下步骤:
启动 Visual Studio。
在菜单栏上,选择**“文件”,“新建**、“项目”。
将打开**“新建项目”**对话框。
在 已安装,模板 类别中,选择 Visual Basic 或 Visual C#,然后选择 窗口。 从项目类型列表中选择 WPF 应用程序 。
输入 AsyncReturnTypes 作为项目的名称,然后选择 确定 按钮。
新项目出现在**“解决方案资源管理器”**中。
在 Visual Studio 代码编辑器"中,选择 MainWindow.xaml 选项。
如果看不到选项卡,打开 MainWindow.xaml 的快捷菜单在 解决方案资源管理器,然后选择 打开。
在 XAML 窗口 MainWindow.xaml 中,用以下代码替换代码。
<Window x:Class="MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://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>
<Window x:Class="AsyncReturnTypes.MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://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.cs 的快捷菜单,然后选择 查看代码。
用下面的代码替换在 MainWindow.xaml.vb 或 MainWindow.xaml.cs 的代码。
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 &= String.Format("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 &= String.Format(vbCrLf & "Value of result1 variable: {0}" & vbCrLf, result1) textBox1.Text &= String.Format("Value of result2 variable: {0}" & vbCrLf, result2) textBox1.Text &= String.Format("Value of resultTask.Result: {0}" & vbCrLf, integerTask.Result) ' 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 &= String.Format(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 &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf) ' This method has no return statement, so its return type is Task. End Function End Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace AsyncReturnTypes { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } // VOID EXAMPLE private async void button1_Click(object sender, RoutedEventArgs e) { textBox1.Clear(); // Start the process and await its completion. DriverAsync is a // Task-returning async method. await DriverAsync(); // Say goodbye. textBox1.Text += "\r\nAll done, exiting button-click event handler."; } async Task DriverAsync() { // Task<T> // Call and await the Task<T>-returning async method in the same statement. int result1 = await TaskOfT_MethodAsync(); // Call and await in separate statements. Task<int> integerTask = TaskOfT_MethodAsync(); // You can do other work that does not rely on integerTask before awaiting. textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n"); int result2 = await integerTask; // Display the values of the result1 variable, the result2 variable, and // the integerTask.Result property. textBox1.Text += String.Format("\r\nValue of result1 variable: {0}\r\n", result1); textBox1.Text += String.Format("Value of result2 variable: {0}\r\n", result2); textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result); // Task // Call and await the Task-returning async method in the same statement. await Task_MethodAsync(); // Call and await in separate statements. Task simpleTask = Task_MethodAsync(); // You can do other work that does not rely on simpleTask before awaiting. textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n"); await simpleTask; } // TASK<T> EXAMPLE async Task<int> TaskOfT_MethodAsync() { // The body of the method is expected to contain an awaited asynchronous // call. // Task.FromResult is a placeholder for actual work that returns a string. var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString()); // The method then can process the result in some way. int leisureHours; if (today.First() == 'S') leisureHours = 16; else leisureHours = 5; // Because the return statement specifies an operand of type int, the // method must have a return type of Task<int>. return leisureHours; } // TASK EXAMPLE async Task Task_MethodAsync() { // 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); // Task.Delay delays the following line by two seconds. textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n"); // This method has no return statement, so its return type is Task. } } }
选择 F5 键运行程序,然后选择 启动 按钮。
下面的输出应显示。
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.
请参见
任务
演练:使用 Async 和 Await 访问 Web(C# 和 Visual Basic)