• c#学习系列相关之多线程(三)----invoke和begininvoke


    一、invoke和BeginInvoke的作用

           invokebegininvoke方法的初衷是为了解决在某个非某个控件创建的线程中刷新该控件可能会引发异常的问题。说的可能比较拗口,举个例子:主线程中存在一个文本控件,在一个子线程中要改变该文本的值,此时会有可能引发异常。windows GUI编程有一个规则,就是只能通过创建控件的线程来操作控件的数据,否则就可能产生不可预料的结果。

    二者的使用情况有两种:

    1.在控件下应用,实例类型是个control例如button等;

    2.在委托下进行使用,实例对象是一个委托类型,在使用时候会跳到当前线程。

    invoke和begininvoke的区别:

    1、Invoke() 调用时,Invoke会阻止当前主线程的运行,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念。
    2、BeginInvoke() 调用时,当前线程会启用线程池中的某个线程来执行此方法,BeginInvoke不会阻止当前主线程的运行,而是等当前主线程做完事情之后再执行BeginInvoke中的代码内容,表现出“异步”的概念。在想获取 BeginInvoke() 执行完毕后的结果时,调用EndInvoke() 方法来获取。而这两个方法中执行的是一个委托。

    二、Invke用法示例

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading;
    6. using System.Threading.Tasks;
    7. namespace 线程test1005
    8. {
    9. public delegate void test(string s1);
    10. class Program
    11. {
    12. static void Main(string[] args)
    13. {
    14. test tt = new test(t1);
    15. Thread thread = new Thread(() => {
    16. tt.Invoke("你好");
    17. });
    18. thread.Start();
    19. string obj = Thread.CurrentThread.ManagedThreadId.ToString();
    20. Console.WriteLine("主线程的ID" + " :" + obj);
    21. Console.Read();
    22. }
    23. static void t1(string s1)
    24. {
    25. string obj = Thread.CurrentThread.ManagedThreadId.ToString();
    26. Console.WriteLine(s1+"支线程的ID" +" :"+obj);
    27. }
    28. }

    提示:本人准备建立一个技术交流群,会将日常学习工作中遇到的问题和解决方案进行分享,同时也会将代码和学习资料上传进去,有什么不懂的问题可以咨询我!+v:SJS66-12

    生活所迫打个广告,本人也代购莆田鞋,不是中间商,工厂直接取货,价格优惠质量保证,都是我自己前去挑选,可以视频选购验货!!希望大家支持!!!赚点生活费!!!+v:SJS66-12
     

    三、BeginInvoke用法示例

    invoke和begininvoke对比:

    1.invoke用法:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading;
    6. using System.Threading.Tasks;
    7. namespace 线程test1005
    8. {
    9. public delegate void test(string s1);
    10. class Program
    11. {
    12. static void Main(string[] args)
    13. {
    14. test tt = new test(t1);
    15. tt.Invoke("你好");
    16. for (int i = 0; i < 300; i++)
    17. {
    18. Console.Write(3);
    19. }
    20. Console.Read();
    21. }
    22. static void t1(string s1)
    23. {
    24. for (int i = 0; i < 300; i++)
    25. {
    26. Console.Write(2);
    27. }
    28. string obj = Thread.CurrentThread.ManagedThreadId.ToString();
    29. Console.WriteLine(s1+"支线程的ID" +" :"+obj);
    30. }
    31. }
    32. }

    由结果可以看出invoke是依次按顺序向下执行;

    2.beginInvoke用法:

    首先介绍一下begininvoke的参数,其中作重要的就是后两个参数这里使用了BeginInvoke方法的最后两个参数,如果被调用的方法含有参数的话,这些参数将作为BeginInvoke的前面一部分参数,(就是 传入调用方法的参数)如果没有参数,BeginInvoke就只有两个参数。第一个参数是回调方法委托类型,这个委托只有一个参数,就是IAsyncResult,如MethodCompleted方法所示。当method方法执行完后,系统会自动调用MethodCompleted方法,传入的其实也是调用方法的返回类型,BeginInvoke的第二个参数需要向MethodCompleted方法中传递一些值,一般可以传递被调用方法的委托类型。

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading;
    6. using System.Threading.Tasks;
    7. namespace 线程test1005
    8. {
    9. public delegate void test(string s1);
    10. class Program
    11. {
    12. static void Main(string[] args)
    13. {
    14. test tt = new test(t1);
    15. tt.BeginInvoke("111", (a) =>
    16. {
    17. for (int i = 0; i < 300; i++)
    18. {
    19. Console.Write(1);
    20. }
    21. }, null);
    22. for (int i = 0; i < 300; i++)
    23. {
    24. Console.Write(3);
    25. }
    26. Console.Read();
    27. }
    28. static void t1(string s1)
    29. {
    30. for (int i = 0; i < 300; i++)
    31. {
    32. Console.Write(2);
    33. }
    34. string obj = Thread.CurrentThread.ManagedThreadId.ToString();
    35. Console.WriteLine(s1+"支线程的ID" +" :"+obj);
    36. }
    37. }
    38. }

    由运行结果可以知道,begininvoke可以继续执行调用方法后的函数,关于begininvoke的具体用法可以参考该文章:Delegate的BeginInvoke()_begininvoke参数-CSDN博客

    例子:

    1. static void Main(string[] args)
    2. {
    3. Console.WriteLine("主线程的ID:" + Thread.CurrentThread.ManagedThreadId);//标记显示主 线程ID
    4. SayHello sayhello = new SayHello(Say);
    5. IAsyncResult iResult=sayhello.BeginInvoke("Olive",new AsyncCallback(Result), sayhello);//三个参数:1、Say()函数的参数,2、AsyncCallback类型的委托,(异步操作结束后执行的委托函数),3、将sayhello对象作为状态参数,在Result函数中会有用到该参数
    6. Console.ReadKey();
    7. }
    8. //AsyncCallback委托所执行的函数
    9. private static void Result(IAsyncResult iasyncresult)
    10. {
    11. SayHello sayhello = (SayHello)iasyncresult.AsyncState;//获取IAsyncResult对象的AsyncState的属性,即为Delegate.BeginInvoke()的第三个参数即sayhello。
    12. string s = sayhello.EndInvoke(iasyncresult);
    13. Console.WriteLine(s + "------好了,异步调用到这里已经结束了");
    14. }
    15. private static string Say(string name)
    16. {
    17. Console.WriteLine("Hello!--------" + name);
    18. Console.WriteLine("当前的线程ID为:" + Thread.CurrentThread.ManagedThreadId);
    19. return "I Love you " + name;
    20. }

    提示:1.begininvoke的返回值类型为IAsyncResult ,并且返回值会继续作为参数传入后续的AsyncCallback回调函数中Result。

    2.函数的实际返回值需要通过EndInvoke进行获取!

    参考文章:

    控件和delegate的Invoke、BeginInvoke用法总结及基本逻辑_richtextbox1.begininvoke_勉之1.2.6的博客-CSDN博客C# 关于Invoke(详解)_c# invoke-CSDN博客

    BeginInvoke 用法 2 - 异步返回_begininvoke用法-CSDN博客

    C#学习笔记--BeginInvoke和EndInvoke的基本用法-CSDN博客

  • 相关阅读:
    遗传算法在TSP中的两步求解(Matlab代码实现)
    分布式物联网平台特点
    有什么实用的拍照识别文字技巧?电脑怎么拍照识别文字
    Flink 1.13 源码解析——TaskManager启动流程 之 初始化TaskExecutor
    java和数据库之间的关系,看这一篇就足够~~~
    WPF动画小知识
    python的re正则表达式
    Java 注解
    Rust 使用egui创建一个简单的下载器demo
    UDP 的报文结构
  • 原文地址:https://blog.csdn.net/qiaodahua/article/details/133688155