• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > .NET中的async和await关键字使用及Task异步调用实例

.NET中的async和await关键字使用及Task异步调用实例

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了async await,c async await,nodejs async await,js async await,node async await等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

其实早在.NET 4.5的时候M$就在.NET中引入了async和await关键字(VB为Async和Await)来简化异步调用的编程模式。我也早就体验过了,现在写一篇日志来记录一下顺便凑日志数量(以后面试之前可以用这个“复习”一下)。

(一)传统的异步调用

在比较“古老”的C#程序中经常可以看到IAsyncResult、BeginInvoke之类的异步调用“踪迹”。先来简单的复习一下吧。

假如我们有一个方法生成字符串,而生成这个字符串需要10秒中的时间:
public class WasteTimeObject
{
    public string GetSlowString(int begin, int length)
    {
        StringBuilder sb = new StringBuilder();

        for (int i = begin; i < begin + length; i++)
        {
            sb.Append(WasteTime(i) + " ");
        }

        return sb.ToString();
    }

    private string WasteTime(int current)
    {
        System.Threading.Thread.Sleep(1000);
        return current.ToString();
    }
}
</div>

我们再做一个窗口,用来请求这个方法并把字符串显示到文本框中。使用同步调用肯定会把UI线程阻塞掉,要想不把UI阻塞掉就要另起一个线程了。基本的步骤如下:

创建一个异步调用的委托:
public delegate string GetSlowStringDelegate(int begin, int length);
</div>

然后呢,再异步调用这个委托:
private void button1_Click(object sender, EventArgs e)
{
    WasteTimeObject ad = new WasteTimeObject();
    GetSlowStringDelegate d = ad.GetSlowString;

    textBox1.Text = "Requesting string, please wait...";

    IAsyncResult ar = d.BeginInvoke(1, 10, TaskComplete, d);
}
</div>

这里的BeginInvoke会在原来的基础上再附加两个参数:表示执行完毕后的回调方法AsyncCallBack,最后一个参数可以是任何对象,以便从回调方法中访问它。不过一般情况都是传递的委托实例,以便获取调用的结果。

当然我们也可以不用回调方法,这样就只好不断地循环查询是否执行完成了。

然后我们就要编写AsyncCallBack这个回调方法了,它接受一个IAsyncResult类型的对象表示异步调用的结果:
private void TaskComplete(IAsyncResult ar)
{
    if (ar == null) return;
    GetSlowStringDelegate d = ar.AsyncState as GetSlowStringDelegate;
    if (d == null) throw new Exception("Invalue object type");
    string result = d.EndInvoke(ar);
    this.Invoke(new Action(() => UpdateTextResult(result)));
}
</div>

调用委托实例的EndInvoke方法并传入IAsyncResult类型的对象用以获取GetSlowString的返回结果。

回调方法是委托线程调用的,因此它不能直接访问UI,所以我们使用窗体的Invoke方法在主线程中显示结果。如果委托方法抛出异常,将会在EndInvoke时抛出。

(二)使用Task类型

可以看到使用传统的办法编写异步调用很麻烦,特别是如果这种调用很多,那么我们的程序就会变成很复杂,逻辑很乱。

.NET 4.5提供的新的异步变成模式就很好地解决了这个问题(其实本质上应该是.NET自动实现了很多操作),使编写异步代码和同步调用一样逻辑清晰。

首先来看看微软的例子:

private async Task SumPageSizesAsync()
{
    // To use the HttpClient type in desktop apps, you must include a using directive and add a
    // reference for the System.Net.Http namespace.
    HttpClient client = new HttpClient();

    // Equivalently, now that you see how it works, you can write the same thing in a single line.
    byte[] urlContents = await client.GetByteArrayAsync(url);
    // . . .
}
</div>

可以看出,使用await关键字后,.NET会自动把返回结果包装在一个Task类型的对象中。对于这个示例,方法是没有返回结果的。而对有返回结果的方法,就要使用Task<T>了:

public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}
</div>

总而言之,使用await表达式时,控制会返回到调用此方法的线程中;在await等待的方法执行完毕后,控制会自动返回到下面的语句中。发生异常时,异常会在await表达式中抛出。

对于我们这个例子,我们编写的代码如下:
private async void button1_Click(object sender, EventArgs e)
{
    textBox1.Text = "Requesting string, please wait...";

    WasteTimeObject ad = new WasteTimeObject();

    string result = await Task.Run(() => ad.GetSlowString(1, 10));

    //Update UI to display the result
    textBox1.Text = result;
}
</div>

我们使用Task类新建一个工作线程并执行。当然我们也可以像M$给的例子那样改造一下GetSlowString,这样就不需要加上Task.Run了。(基本上,这种方法都会以Async后缀结尾。)

如何?原来的:创建异步委托→回调一气呵成。另外还有一点,await下面的语句是由主线程调用的,不是由新的线程调用,所以我们可以直接访问UI。

(三)取消执行和显示进度

最后一个要记录的,就是如何给异步调用添加进度条,并能让用户取消操作。界面就是下面这样:

使用最终完成的代码来说明吧。首先改造GetSlowString方法,使之支持取消和汇报进度:

public string GetSlowString(int begin, int length, IProgress<int> progress, CancellationToken cancel)
{
    StringBuilder sb = new StringBuilder();

    for (int i = begin; i < begin + length; i++)
    {
        sb.Append(WasteTime(i) + " ");

 &nbs

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 浅谈Async和Await如何简化异步编程(几个实例让你彻底明白)
  • 关于async和await的一些误区实例详解
  • .NET中的async和await关键字使用及Task异步调用实例
  • async and await 的入门基础操作

相关文章

  • 2017-05-28C#语言中条件与&&与条件或||的区别
  • 2017-05-28常用正则 常用的C#正则表达式
  • 2017-05-28.net 一些无法catch的异常
  • 2017-05-28C#中前台线程和后台线程的区别与联系
  • 2017-05-28C#垃圾回收机制的详细介绍
  • 2017-05-28C#使用foreach语句遍历二维数组的方法
  • 2017-05-28des加密解密源码 C# key值问题分析
  • 2017-05-28C#在RichTextBox中显示不同颜色文字的方法
  • 2017-05-28c# 解决IIS写Excel的权限问题
  • 2017-05-28C#操作目录与文件的方法步骤

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • winform C#获得Mac地址,IP地址,子网掩码,默认网关的实例
    • C#修改及重置电脑密码DirectoryEntry实现方法
    • 深入多线程之:解析线程的交会(Thread Rendezvous)详解
    • 字符串和十六进制之间的转换方法实例
    • 通过特性(attribute)为枚举添加更多信息示例
    • C# Linq读取XML文件的实例
    • c# n个数排序实现代码
    • winform中写app.config文件时调试情况下没有改变的原因
    • C#静态构造函数用法实例分析
    • C#使用IComparer自定义List类实现排序的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有