• [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序


    [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序

    本节导读:

    本节主要说明使用异步进行程序设计的优缺点及如何通过异步编程.

    使用传统方法BeginInvoke / EndInvoke来实现异步。

    使用async/await 创建异步方法和事件。

    通过异步编程创建具有快速响应和可伸缩性的应用程序。 

    读前必备:

    A.委托 [.net 面向对象编程基础]  (21) 委托

    B.事件 [.net 面向对象编程基础] (22) 事件

    1.异步程序设计的优缺点:

    A.让用户界面快速响应;对于耗时操作阻塞UI线程,通过异步回调可使用UI快速响应。

    B.创建高伸缩性的应用。对于服务端应用,创建更多线程来处理消耗资源较多,使用异步可使用主线程继续工作,不需要等待返回。使用程序具有更好的伸缩性。

    对于异步的缺点,最主要一点就是比创建同步程序难度大一些,首先使用传统的方法创建异步,比起同步更容易出错。不过随着.NET的不断发展和第三方异步组件的丰富,创建异步应用程序也变得越来越简单了。

    2.异步的实现

    对于.NET中的异步编程,.NET在各个方向都几乎提供了同步和异步的两个方式来实现,在这里我们不能把.NET中全部的异步编程方法都列举出来了,下面介绍几种常用且实用的异步方法。

    3.使用BeginInvoke / EndInvoke实现异步

    3.1 简单的异步示例

    下面看一个简单的示例: 

    //使用一个有返回值的泛型委托来执行BeginInvoke
    Func<string> myFunc = new Func<string>(()=>{
        Thread.Sleep(10);
        return "我是异步执行完成的返回值 当前时间:" + System.DateTime.Now.ToString();
    });
    IAsyncResult asynResult = myFunc.BeginInvoke(null, null);
    //在异步没有完成前,可以做别的事
    while (!asynResult.IsCompleted)
    {
        //当不是true时,就执行这里的代码
        Console.WriteLine("当前异步是否完成:" + asynResult.IsCompleted + " 当前时间:" + System.DateTime.Now.ToString());
    }
    string result = myFunc.EndInvoke(asynResult);//当是true时,就将结果返回显示
    
    Console.WriteLine(result);

     运行结果如下:

     

    在异步没有完成时,可以继续工作做一些想做的事,异步完成后返回结果。

    3.2 使用异步的超时 WaitOne 判断异步完成

    除了上面使用IsCompleted来判断异步完成之外,也可以使用超时来判断异步的完成情况

    示例如下 :

    //使用一个有返回值的泛型委托来执行BeginInvoke
    Func<string> myFunc = new Func<string>(()=>{
        int i = 0;
        while (i<99999999)
            ++i;
        return "异步执行完成的返回值" + (i).ToString() + " 当前时间:" + System.DateTime.Now.ToString();
       
    });
    IAsyncResult asynResult = myFunc.BeginInvoke(null, null);
    
    while (!asynResult.AsyncWaitHandle.WaitOne(10, false))
        Console.Write("*");
    
    string result = myFunc.EndInvoke(asynResult);
    Console.Write("
    ");
    Console.WriteLine(result);

    运行结果如下:

    3.3 回调

    毕竟上述两种等待不是一个好的方法。我们在前端开发中使用过ajax的同学肯定知道,前端中异步使用一个回调函数在异步完成后完成我们想要做的事,.NET自然也有类似的回调方法,

    看示例:

               
    //使用一个有返回值的泛型委托来执行BeginInvoke
    Func<string> myFunc = new Func<string>(()=>{
        int i = 0;
        while (i<99999999)
            ++i;
        return "异步执行完成的返回值" + (i).ToString() + " 当前时间:" + System.DateTime.Now.ToString();
       
    });
    IAsyncResult asynResult = myFunc.BeginInvoke((result) =>
    {
        string rst = myFunc.EndInvoke(result);
        Console.WriteLine("异步完成了,我该返回结果了!");
        Console.WriteLine(rst);
    }, null);

    运行结果如下 :

    3.4 其它组件中的BeginEnd异步方法

    除了BeginInvoke / EndInvoke之外,.NET在很多类中提供了异步的方法,

    如System.Net.HttpWebRequest类的BeginGetResponse和EndGetResponse方法,

    这里不再一一列举了,使用方法和上面的示例类似。

     4. async/await  

    .NET 5.0 以后,让异步编程变得更加简单了,我们介绍一下async和await。 

    它让我们编写异步程序变得和同步一样简单,不但减少了代码量,而且不会因为异步让我们程序逻辑被打乱。 

    4.1 异步方法 

    下面使用async 和 await关键字来创建一个异步方法,

    在第一个方法里调用第二个异步方法,

    第二个异步方法中使用了多线程。

    听起来很绕口,不过整个代码编写和同步方法没有什么区别,只是多一个关键字。

    static void Main(string[] args)
    {
        Console.WriteLine("主线程开始..");
        AsyncMethod();
        Thread.Sleep(1000);
        Console.WriteLine("主线程结束..");
    
    
        Console.ReadKey();
    }
    
    static async void AsyncMethod()
    {
        Console.WriteLine("开始异步方法");
        var result = await MyMethod();
        Console.WriteLine("异步方法结束");
    }
    
    static async Task<int> MyMethod()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("异步执行" + i.ToString() + "..");
            await Task.Delay(1000); //模拟耗时操作
        }
        return 0;
    }

    运行结果如下: 

     

    4.2 异步事件

    下面使用一个WinForm应用程序来测试一下异步事件,我们创建一个同步的Click事件和一个异步的Click事件,先触发异步,然后紧接着触发同步,看一下运行结果。 

    //同步事件
    private void button2_Click(object sender, EventArgs e)
    {
        textBox1.Text += "同步执行开始..
    ";          
        MyMethodFirst();
        textBox1.Text += "同步执行结束..
    ";          
    }
    //同事事件调用方法
    int MyMethodFirst()
    {
        for (int i = 0; i < 5; i++)
        {
            textBox1.Text += "同步执行" + i.ToString() + "..
    ";               
        }
        return 0;
    }
    
    //异步事件
    private async  void button3_Click(object sender, EventArgs e)
    {
        textBox1.Text += "异步执行开始..====
    ";
        await MyMethodSencond();
        textBox1.Text += "异步执行结束..====
    ";     
    }
    //异步事件调用方法
    async Task<int> MyMethodSencond()
    {
        for (int i = 0; i < 5; i++)
        {
            textBox1.Text += "异步执行" + i.ToString() +" ..====
    ";          
            await Task.Delay(1000); //模拟耗时操作
        }
        return 0;
    }

     运行结果如下:

    5. 本节要点

    A.使用传统方法BeginInvoke / EndInvoke来实现异步

    B.使用async/await 创建异步方法和事件

    ==============================================================================================

    返回目录

    <如果对你有帮助,记得点一下推荐哦,如有有不明白或错误之处,请多交流>

    <对本系列文章阅读有困难的朋友,请先看《.net 面向对象编程基础》>

    <转载声明:技术需要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>

    .NET 技术交流群:467189533 .NET 程序设计

    ==============================================================================================

  • 相关阅读:
    aidl 详解
    为什么我选择用 flutter
    hunting
    Dynamic programming
    android 微信开发交流群
    hash function 字符串哈希函数
    函数也可以看成是空间的变换
    语法树
    生活中的物理随处可见
    about coroutine
  • 原文地址:https://www.cnblogs.com/yubinfeng/p/4687904.html
Copyright © 2020-2023  润新知