返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C#线程委托BeginInvoke与EndInvoke的用法
  • 250
分享到

C#线程委托BeginInvoke与EndInvoke的用法

2024-04-02 19:04:59 250人浏览 泡泡鱼
摘要

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

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

1. BeginInovke和EndInvoke简单介绍

delegate long MyDel(int first, int second);

class Program
{
    static long Sum(int x, int y)
    {
        Console.WriteLine("------Inside Sum@{0}", DateTime.Now.ToString());
        Thread.Sleep(2000);
        return x + y;
    }

    static void Main(string[] args)
    {
        MyDel del = new MyDel(Sum);

        Console.WriteLine("Before BeginInvoke---@{0}", DateTime.Now.ToString());
        IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
        Console.WriteLine("After BeginInvoke@{0}", DateTime.Now.ToString());

        Console.WriteLine("Doing stuff@{0}", DateTime.Now.ToString());

        long result = del.EndInvoke(iar);
        Console.WriteLine("End Invoke@{0}", DateTime.Now.ToString());

        Console.WriteLine("After EndInvoke:  {0}", result);

        Console.ReadKey();

    }
}

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

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

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

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

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

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

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

2.BeginInovke和EndInvoke详细

对于 BeginInvoke 方法,有几个注意的地方

① 我们可以根据上面的代码知道,BeginInvoke的参数包含如下两个部分

  • 引用方法的参数
  • CallBack参数和State参数

②BeginInvoke 会在线程池中找到一个线程,让引用方法运行在该线程上

③BeginInvoke 返回给调用线程一个实现IAsyncResult接口的对象的引用。这个接口引用包含了在线程池线程中运行的异步方法的状态。可以判断这个状态来确定异步方法是否结束。

// 3和5是引用方法参数,两个null分别是Callback参数和State参数
// iar是新线程的信息
IAsyncResult iar = del.BeginInvoke(3, 5, null, null);

对于 EndInvoke 方法,有几个注意的地方

①他的参数是上面BegionInvoke返回的IAsyncResult接口的引用对象,传入这个对象是便于EndInvoke去找到引用方法运行的线程。并且这个参数置于参数列表最后一个。EndInvoke提供了从异步方法调用的所有输出,包括ref和out参数。如果委托的引用方法有ref和out参数,他们必须包含在EndInvoke的参数列表当中

IAsyncResult iar2 = del2.BeginInvoke(3, 5, out res, null, null);
del2.EndInvoke(out res, iar2);

②如果线程已经退出了,EndInvoke会做如下事情:

  • 清理退出的线程的状态并且释放资源
  • 找到引用方法的返回值,并作为自己的返回值

③如果EndInovke发现线程还在运行中,那么调用线程就会停止并等待,直到清理完毕并返回值。

④因为EndInvoke会去清理线程信息,所以BeginInvoke和EndInvoke必须成对使用。

⑤如果异步方法出现异常,那么在调用EndInvoke的时候会抛出异常。

3.AsyncResult类

上面说BeginInvoke方法返回了一个IAsyncResult接口的引用对象(内部是AsyncResult类的对象),AsyncResult类型表现了异步方法的状态。下面是这类的主要组成部分:

4.三种模式

① 等待-直到完成 (比较简单的模式)

//开始执行异步方法
IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
//Do Something 耗时
del2.EndInvoke(iar);

像上面的代码,BeginInvoke之后,做了一些事情,然后调用EndInvoke来处理结果,这种方式就是等待-直到完成的模式。

②轮询模式

轮询模式中,原始的线程发起了异步的方法调用,做一些事情,然后使用IAsyncResult中的IsComplete熟悉来定期检查开启的线程是否完成。如果未完成就在去做一些其他事情。

delegate long MyDel(int first, int second);

class Program
{
    static long Sum(int x, int y)
    {
        Console.WriteLine("--Inside Sum@{0}", DateTime.Now.ToString());
        Thread.Sleep(200);
        return x + y;
    }

    static void Main(string[] args)
    {
        MyDel del = new MyDel(Sum);
        //开始执行异步方法
        IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
        //轮询开始
        while (!iar.IsCompleted)
        {
            //未完成,执行下面的语句
            for (long i = 0; i < 20000000; i++)
                ;
        }
        //执行完成调用EndInvoke获取结果
        long result = del.EndInvoke(iar);
        Console.ReadKey();
    }
}

③回调模式

前两种都是主动方式的,原始线程一直在监控这新开启的线程。但是回调是被动的,一旦原始线程发起了异步方法,它就自己管自己了,不在考虑同步。

当异步方法调用结束之后,系统调用一个用户自定义的方法来处理结果,并且调用委托的EndInvoke方法。这个用户自定义的方法就是回调方法。

上面的BegionInvoke中写过,他会有两个参数一个Callback参数和一个State参数.

CallBack参数:是回调方法的名称。

State参数:可以是null,或者传入回调方法的一个对象的引用。我们可以用IAsyncResult参数的AsyncState属性来获取这个对象,参数的类型是object。

a.回调方法:

回调方法的签名和返回类型必须和 AsyncCallback委托类型所描述的形式一致。

两种方式,构建这个AsyncCallback参数

new AsyncCallback 对象  

IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone),null);

直接传回调方法的名称

IAsyncResult iar = del.BeginInvoke(3, 5, CallWhenDone, null);

其中 CallWhenDone 如下:

static void CallWhenDone(IAsyncResult iar)
{
    AsyncResult ar = (AsyncResult)iar;
    MyDel del = (MyDel)ar.AsyncDelegate;
    //回调方法中调用了EndInvoke
    long result = del.EndInvoke(iar);
}

b.在回调方法中调用EndInvoke

上面代码中,在回调中使用了EndInvoke,上文中说到 EndInvoke的调用,是委托的调用,并且需要传入一个IAsyncResult的接口对象的引用。

所以想要在回调方法里面,调用这个EndInvoke,就得拿到两个东西一个是委托对象、一个是IAsyncResult,由于我们AsyncCallback委托本身就是必须要传入IAsyncResult 的,所以这个比较容易,剩下的就是委托对象本身了。在AsyncResult类小节里面我看到,它里面存着一个 AsyncDelegate(它就是委托对象的引用),还有就是 IAsyncResult接口对象在内部就是AsyncResult类对象。所以才可以像上main的代码,通过强制类型转换得到MyDel的对象。

第二种方法就是如果State参数没有用处,可以通过State参数,把委托的对象传过去。

调用的地方,最后一个参数传入del

IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone),del);

回调方法:

static void CallWhenDone(IAsyncResult iar)
{
    MyDel del = (MyDel)iar.AsyncState;
    long result = del.EndInvoke(iar);
}

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对编程网的支持。

--结束END--

本文标题: C#线程委托BeginInvoke与EndInvoke的用法

本文链接: https://lsjlt.com/news/154236.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C#线程委托BeginInvoke与EndInvoke的用法
    我们已经知道 C#当中 存在async/await 、BackGroudWorker类以及TPL(任务并行库)。当然C#还有一些旧的模式来支持异步编程。 1. BeginInovke...
    99+
    2024-04-02
  • C#线程委托BeginInvoke与EndInvoke怎么使用
    这篇文章主要讲解了“C#线程委托BeginInvoke与EndInvoke怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#线程委托BeginInvoke与EndInvoke怎么使用...
    99+
    2023-07-02
  • c#委托的常见用法
    C#委托是一种引用类型,可以用于封装方法并传递给其他方法,常见的用法有以下几种:1. 事件处理: 委托可以用于处理事件,当事件触发时,委托可以调用相应的方法来处理事件。例如,可以使用EventHandler委托来处理按钮的点击事件。2....
    99+
    2023-08-09
    C#
  • C#委托用法详解
    目录1、什么是委托2、委托的定义3、委托的实例化3.1 使用new关键字3.2 使用匿名方法3.3 使用Lambda表达式4、泛型委托5、C#内置泛型委托6、多播委托1、什么是委托 ...
    99+
    2024-04-02
  • c#多线程通信之委托事件
    在研究c# 线程之间通信时,发现传统的方法大概有三种: 全局变量,由于同一进程下的多个进程之间共享数据空间,所以使用全局变量是最简单的方法,但要记住使用volatile进行限制...
    99+
    2024-04-02
  • C#委托的用法有哪些
    C#委托的用法有以下几种:1. 作为回调函数:委托可以用于将一个函数作为参数传递给另一个函数,以便在需要的时候调用。这种用法常用于异...
    99+
    2023-08-09
    C#
  • C#如何使用异步委托开启线程
    这篇文章主要为大家展示了“C#如何使用异步委托开启线程”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C#如何使用异步委托开启线程”这篇文章吧。异步委托开启线程 public ...
    99+
    2023-06-17
  • C# MethodInvoker委托的使用
    MethodInvoker委托是C#中的一个预定义委托,用于引用无参数且无返回值的方法。它可以用于在不同的线程中调用方法。使用Met...
    99+
    2023-09-01
    C#
  • C#异步委托和多线程怎么理解
    这篇文章主要讲解了“C#异步委托和多线程怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#异步委托和多线程怎么理解”吧!关于这个问题,我想很多初学者跟我一样有很多疑问吧。下面我说的内...
    99+
    2023-06-18
  • C#---事件委托EventHandler的定义与使用
    在C#中,事件委托是一种特殊的委托类型,用于定义事件的回调函数。它是一种封装了方法的类型,用于在事件发生时通知其他对象进行响应。事件...
    99+
    2023-09-08
    C#
  • 详解C#中委托的概念与使用
    目录委托的概念多播委托拖动按钮委托的概念 委托这个名字取的神乎其神的,但实质是函数式编程,把函数作为参数传递给另一个参数。对于C语言程序员来说,就是把函数指针当作参数传递给另一个函数...
    99+
    2023-02-27
    C#委托使用 C#委托
  • C#中委托的概念与使用方法是什么
    本篇内容主要讲解“C#中委托的概念与使用方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#中委托的概念与使用方法是什么”吧!委托的概念委托这个名字取的神乎其神的,但实质是函数式编程,把...
    99+
    2023-07-05
  • C#委托的使用方法是什么
    在C#中,委托是一种类型,用于引用一个或多个方法。委托可以看作是函数指针,它可以被用来调用方法。 使用委托的步骤如下: 定义委托:...
    99+
    2024-03-06
    C#
  • C#异步委托之委托使用的时机有哪些
    这篇文章将为大家详细讲解有关C#异步委托之委托使用的时机有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在我的印象里,委托经常出现在三个场合(也许更多,我水平有限)。C#异步委托之委托使用的时机1、事...
    99+
    2023-06-18
  • c#中Invoke与BeginInvoke的用法及说明
    目录c# Invoke与BeginInvoke先讲下InvokeBeginInvoke总结c# Invoke与BeginInvoke 最近在学习线程时,发现当我创建的线程需要访问UI...
    99+
    2023-01-28
    c# Invoke c# BeginInvoke c# Invoke与BeginInvoke
  • C#中委托的基础入门与实现方法
    目录前言关于委托委托的实现一、基本实现方式二、使用委托时的一些特殊方式1、委托实例对象的创建多元化:2、事件绑定的多种方式三、委托的几种特殊实现方式1,使用Action方法2,使用F...
    99+
    2024-04-02
  • C#中委托的基础介绍与实现方法
    这篇文章主要讲解了“C#中委托的基础介绍与实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#中委托的基础介绍与实现方法”吧!目录前言关于委托委托的实现一、基本实现方式二、使用委托时的...
    99+
    2023-06-20
  • C#中匿名方法与委托的关系介绍
    当对2个数实现加减乘除,其中的一个解决方案是通过委托来实现。如下: class Program { private delegate int Cacu...
    99+
    2024-04-02
  • c#委托与事件的区别是什么
    C#中的委托和事件都可以用于实现事件驱动的编程模型,但它们之间有一些重要的区别: 委托是一种数据类型,用于存储对一个或多个方法的...
    99+
    2024-04-02
  • C# Invoke,begininvoke的用法详解
    在C#中,Invoke和BeginInvoke是用于在多线程编程中调用委托的方法。委托是一种可以存储对方法的引用的类型,可以用于异步...
    99+
    2023-08-08
    C#
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作