使用 async 修饰符可将方法、lambda 表达式或匿名方法指定为异步。如果对方法或表达式使用此修饰符,则其称为异步方法。如下示例定义了一个名为 FF异步示例 的异步方法:
public async Task < int > FF异步示例 ( )
{
//……
}
如下的代码常见于异步方法中,且使用 HttpClient . GetStringAsync 方法:
static readonly HttpClient client = new ( );
static async Task Main ( string [ ] args )
{
// 在 try / catch 块中调用异步网络方法来处理异常
try
{
// using HttpResponseMessage response = await client . GetAsync ( "http://www.contoso.com/" );
// response . EnsureSuccessStatusCode ( );
// string responseBody = await response . Content . ReadAsStringAsync ( );
// 上面的三行代码可以用下面的 new helper 方法代替
string responseBody = await client . GetStringAsync ( "http://www.contoso.com/" );
Console . WriteLine ( responseBody );
}
catch ( HttpRequestException e )
{
Console . WriteLine ( "\n异常!" );
Console . WriteLine ( $"信息:{e . Message} " );
}
}
异步方法同步运行,直至到达其第一个 await 表达式,此时会将方法挂起,直到等待的任务完成。同时,如下节示例中所示,控件将返回到方法的调用方。
如果 async 关键字修改的方法不包含 await 表达式或语句,则该方法将同步执行。编译器警告(CS4014)将通知你不包含 await 语句的任何异步方法,因为该情况可能表示存在错误。
async 关键字是上下文关键字,原因在于只有当它修饰方法、lambda 表达式或匿名方法时,它才是关键字。在所有其他上下文中,都会将其解释为标识符。
示例
下面的示例展示了异步事件处理程序 annKS_Click 和异步方法 FFasyncInt 之间的控制结构和流程。此异步方法的结果是 Web 页面的字符数。此代码适用于在 Visual Studio 中创建的 Windows Presentation Foundation(WPF)应用或 Windows 应用商店应用;参见有关设置应用的代码注释。
可以在 Visual Studio 中将此代码作为 Windows Presentation Foundation(WPF)应用或 Windows 应用商店应用运行。需要一个名为 annKS 的 button 控件和一个名为 wbkJG 的 TextBlock 控件。切勿忘记设置名称和处理程序,以便获得类似于以下代码的内容:
<Grid Margin="0,0,10,365">
<Grid Margin="10,75,0,-355">
<TextBlock x:Name="wbkJG" TextWrapping="Wrap"/>
</Grid>
<Button x:Name="annKS" Content="开始" Margin="10,0,0,0" Click="annKS_Click"/>
</Grid>
若为 WPF 应用程序:
- 添加对 System . Net . Http 的引用
若为 Windows 应用商店应用程序:
- 添加对 System . Net . Http 和 System . Threading . Tasks 的引用
{
public MainWindow()
{
InitializeComponent();
}
private async void annKS_Click ( object sender , RoutedEventArgs e )
{
wbkJG . Text = "";
wbkJG . Text += "开始异步操作:\n";
try
{
int CD = await FFasyncInt ( );
// 请注意,您可以将 “await FFasyncInt ( )” 放在 “CD” 所在的下一行,但由于 ‘+=’ 获取 wbkJG 的值时,您不会看到 FFasyncInt 设置文本的全局副作用
wbkJG . Text += $"长度:{CD:N0}\n";
}
catch ( Exception ex )
{
MessageBox . Show ( ex . Message );
}
}
public async Task<int> FFasyncInt ( )
{
HttpClient KHD = new ( );
int IntL = ( await KHD . GetStringAsync ( "http://msdn.microsoft.com" ) ) . Length;
wbkJG. Text += "准备完成 FFasyncInt。\n";
return IntL;
}
}
返回类型
异步方法可具有以下返回类型:
- Task
- Task < TResult >
- void。对于除事件处理程序以外的代码,通常不鼓励使用 async void 方法,因为调用方不能 await 那些方法,并且必须实现不同的机制来报告成功完成或错误条件
- 任何具有可访问的 GetAwaiter 方法的类型。System . Threading . Tasks . ValueTask < TResult > 类型属于此类实现。它通过添加 NuGet 包 System . Threading . Tasks . Extensions 的方式可用
此异步方法既不能声明任何 in、ref 或 out 参数,也不能具有引用返回值,但它可以调用具有此类参数的方法。
如果异步方法的返回语句指定一个 < TResult > 类型的操作数,则应指定 Task < TResult > 作为方法的返回类型。如果当方法完成时未返回有意义的值,则应使用 Task。 即对方法的调用将返回一个 Task,但是当 Task 完成时,任何等待 Task 的所有 await 表达式的计算结果都为 void。
你应主要使用 void 返回类型来定义事件处理程序,这些处理程序需要此返回类型。void 返回异步方法的调用方不能等待,并且无法捕获该方法引发的异常。
可以返回另一个类型(通常为值类型),该类型具有 GetAwaiter 方法,可最大程度减少代码段性能关键部分中的内存分配。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。