• C# 异步编程Invoke、beginInvoke、endInvoke的用法和作用


    C# 异步编程Invoke、beginInvoke、endInvoke的用法和作用

     一、Invoke

    Invoke的本质只是一个方法,方法一定是要通过对象来调用的。

    一般来说,Invoke其实用法只有两种情况:

    Control的Invoke

    Delegate的Invoke

    也就是说,Invoke前面要么是一个控件,要么是一个委托对象。

    Control的Invoke

    Control的Invoke一般用于解决跨线程访问的问题,比如你想操作一个按钮button,你就要用button.Invoke,你想操作一个文本label,你就要用label.Invoke,但是大家会发现很麻烦,如果我想既操作button,又操作label,能不能写在一起呢?当然可以。

    我们知道,主窗体是一个Form,Form自然也是继承Control的,所以Form也有Invoke的方法,可以直接调用Form.Invoke,这就是我们常见的this.Invoke。这就是为什么有的Invoke前面啥都没有的问题,其实前面是this,只不过省略了。

    示例:

    this.Invoke(new Action(() =>{ button1.Text = "关闭";}));

    Delegate的Invoke

    Delegate的Invoke其实就是从线程池中调用委托方法执行,Invoke是同步的方式,会卡住调用它的UI线程。

    1. void PrintMessage(string message) 
    2.     { 
    3.         Console.WriteLine(message); 
    4.     } 
    5.     MyDelegate myDelegate = PrintMessage; 
    6.     myDelegate.Invoke("Hello, World!"); // 使用 Invoke 方法调用委托引用的方法`

    beginInvoke、endInvoke

    我们已经知道 C#当中 存在async/await 、BackGroudWorker类以及TPL(任务并行库)。当然C#还有一些旧的模式来支持异步编程。

    1.     delegate long MyDel(int first, int second);
    2.     
    3.     class Program
    4.     {
    5.         static long Sum(int x, int y)
    6.         {
    7.             Console.WriteLine("------Inside Sum@{0}", DateTime.Now.ToString());
    8.             Thread.Sleep(2000);
    9.             return x + y;
    10.         }
    11.     
    12.         static void Main(string[] args)
    13.         {
    14.             MyDel del = new MyDel(Sum);
    15.     
    16.             Console.WriteLine("Before BeginInvoke---@{0}", DateTime.Now.ToString());
    17.             IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
    18.             Console.WriteLine("After BeginInvoke@{0}", DateTime.Now.ToString());
    19.     
    20.             Console.WriteLine("Doing stuff@{0}", DateTime.Now.ToString());
    21.     
    22.             long result = del.EndInvoke(iar);
    23.             Console.WriteLine("End Invoke@{0}", DateTime.Now.ToString());
    24.     
    25.             Console.WriteLine("After EndInvoke:  {0}", result);
    26.     
    27.             Console.ReadKey();
    28.     
    29.         }
    30.     }

    如上代码,定义了一个委托 MyDel ,并且在调用的时候把Sum方法传给了它的对象。一般情况下我们调用这个委托对象,它就会调用他调用列表中包含的方法。就想调用方法一样,这是同步完成的。

    但是如果委托对象在调用列表中只有一个方法(引用方法),它就可以异步的去执行这个方法。BeginInovke和EndInvoke就是用来做这个事的。我们可以用如下的方式使用:

    * ①当我们调用BeginInvoke方法的时候,他开始在一个独立的线程上执行引用方法,并且立即返回到原始线程。原始线程可以继续,而引用方法会在想吃的线程中并行执行。
    * ②当程序希望获取已完成的异步方法的结果时,可以检查BeginInvoke返回的IAsyncResult的IsCompleted属性,或者调用委托的EndInvoke方法来等待委托执行完成。

    上面的使用过程就引出的三种模式:

    * ①等待-直到完成 原始线程在发起了异步方法以及做了一些其他处理之后,原始线程就中断并且等待异步方法执行完成之后再继续。

    * ②轮询 ,原始线程定期检查发起的线程是否完成,如果没有则可以继续做其他的事情,

    * ③回调 原始线程一直执行,无需等待或者检查发起的线程是否完成,发起的线程中的引用发放完成之后,发起的线程会调用回调方法,由回调方法在调用的EndInvoke之前处理异步方法的结果。

    借鉴网站:

    C#中Invoke和BeginInvoke实际应用详解_C#教程_脚本之家

    C#线程委托BeginInvoke与EndInvoke的用法_C#教程_脚本之家

  • 相关阅读:
    基于matlab的SVR回归模型
    c 语言基础:L1-032 Left-pad
    ARCGIS PRO SDK 从当前工程中获取相关信息
    数据结构——排序
    重塑DeFi:深入了解Solaris Network
    混合灰狼和布谷鸟搜索优化算法(Matlab完整代码实现)
    Go语言中的init函数: 特点、用途和注意事项
    干了5-6年的测试,没想到最后因为“这个”晋升了,
    LeetCode 0754. 到达终点数字
    绿色创新+绿色质造,群硕OI在“2022国际绿色零碳节”上获奖
  • 原文地址:https://blog.csdn.net/qq_3517289697/article/details/140142939