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

简介: 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用法示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            test tt = new test(t1);
            Thread thread = new Thread(() => {
                tt.Invoke("你好");
            });
            thread.Start();
            string obj = Thread.CurrentThread.ManagedThreadId.ToString();
            Console.WriteLine("主线程的ID" + " :" + obj);
            Console.Read();
        }
        static void t1(string s1)
        {
            string obj = Thread.CurrentThread.ManagedThreadId.ToString();
            Console.WriteLine(s1+"支线程的ID" +" :"+obj);
        }
    }


三、BeginInvoke用法示例

invoke和begininvoke对比:

1.invoke用法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            test tt = new test(t1);
            tt.Invoke("你好");
 
            for (int i = 0; i < 300; i++)
            {
                Console.Write(3);
            }
            Console.Read();
        }
        static void t1(string s1)
        {
            for (int i = 0; i < 300; i++)
            {
                Console.Write(2);
            }
            string obj = Thread.CurrentThread.ManagedThreadId.ToString();
            Console.WriteLine(s1+"支线程的ID" +" :"+obj);
        }
    }
}

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

2.beginInvoke用法:

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 线程test1005
{
    public delegate void test(string s1);
    class Program
    {
         static void Main(string[] args)
        {
            test tt = new test(t1);
            tt.BeginInvoke("111", (a) =>
            {
                for (int i = 0; i < 300; i++)
                {
                    Console.Write(1);
                }
            }, null);
            for (int i = 0; i < 300; i++)
            {
                Console.Write(3);
            }
            Console.Read();
        }
        static void t1(string s1)
        {
            for (int i = 0; i < 300; i++)
            {
                Console.Write(2);
            }
            string obj = Thread.CurrentThread.ManagedThreadId.ToString();
            Console.WriteLine(s1+"支线程的ID" +" :"+obj);
        }
    }
}

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

例子:

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

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

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


相关文章
|
21天前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
|
3天前
|
安全 Java C#
C#多线程详解
C#多线程详解
12 0
|
13天前
|
消息中间件 缓存 Java
【多线程学习】深入探究定时器的重点和应用场景
【多线程学习】深入探究定时器的重点和应用场景
|
13天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
13天前
|
消息中间件 监控 安全
【JAVAEE学习】探究Java中多线程的使用和重点及考点
【JAVAEE学习】探究Java中多线程的使用和重点及考点
|
18天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
1月前
|
C++
C++语言多线程学习应用案例
使用C++ `std::thread`和`std::mutex`实现多线程同步。示例创建两个线程`t1`、`t2`,共享资源`shared_resource`,每个线程调用`increase`函数递增资源值。互斥锁确保在任何时候只有一个线程访问资源,防止数据竞争。最后输出资源总值。
9 1
|
2月前
|
C#
C#学习系列相关之多线程(二)----Thread类介绍
C#学习系列相关之多线程(二)----Thread类介绍
|
21天前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
|
21天前
|
存储 安全 网络安全
C#编程的安全性与加密技术
【4月更文挑战第21天】C#在.NET框架支持下,以其面向对象和高级特性成为安全软件开发的利器。本文探讨C#在安全加密领域的应用,包括使用System.Security.Cryptography库实现加密算法,利用SSL/TLS保障网络传输安全,进行身份验证,并强调编写安全代码的重要性。实际案例涵盖在线支付、企业应用和文件加密,展示了C#在应对安全挑战的同时,不断拓展其在该领域的潜力和未来前景。