C# 异步委托 BeginInvoke EndInvoke

article/2025/9/30 6:30:19

1. 简单主线程中委托:

static void Main(string[] args)
{//定义一个委托,并初始化Func<int, int, string> delFunc = (a, b) => (a + b).ToString();//黄色底纹部分换成{ return (a + b).ToString(); }更好理解//同步方法调用(跟调用一个方法一样),即是主线程执行这个委托string str = delFunc(1, 2);//以往做法Console.WriteLine(str);Console.ReadKey();
}

执行结果

2. 异步委托:

static void Main(string[] args)
{Console.WriteLine("主线程id:"+Thread.CurrentThread.ManagedThreadId);//定义一个委托,并初始化Func<int, int, string> delFunc = (a, b) =>{
//由于下面执行这个委托时使用了BeginInvoke方法,所以就为开启一个新线程去执行,所以称为异步线程Console.WriteLine("异步线程id:" + Thread.CurrentThread.ManagedThreadId);
//Thread.Sleep(3000);return (a + b).ToString();};//同步方法调用,即是主线程执行这个委托//string str = delFunc(1, 2);//BeginInvoke() 方法用于异步委托的执行开始。有返回值,返回值为IAsyncResult,并不是执行委托方法的返回值//BeginInvoke() 是可以接受多个参数的,它的参数个数和参数类型取决于定义委托时的参数个数和类型,无论它有多少个参数,最后两个参数都是不变的。倒数第二个参数为回调函数,暂用null,//最后一个参数是给回调函数传入参数的参数,暂用null//IAsyncResult result = delFunc.BeginInvoke(1, 2, null, null);delFunc.BeginInvoke(1, 2, null, null);//接下来我们看看是不是开启一个新的线程来执行这个委托,因此在最上面先打印出主线程 Console.WriteLine("主线程id:"+Thread.CurrentThread.ManagedThreadId);,改进下委托的初始化Console.WriteLine();Console.ReadKey();
}

输出: 

从上面的执行结果就可以看出,是两个不同的线程在执行。所以称之为异步委托。也就是说使用委托的BeginInvoke方法,本质就是使用了一个线程池的线程去执行委托指向的方法。不是用主线程去执行。

3. 如何拿到异步委托的结果呢?

	//如何拿到异步委托的结果呢,即返回值,这也就是利用异步委托的优势哦,因为手动写线程只能执行没有返回值的委托(ThreadStart、ParameterizedThreadStart),定义如下:public delegate void ThreadStart()public delegate void ParameterizedThreadStart(object obj) 要执行有返回值的委托,就需要使用异步委托执行//1.先拿到BeginInvoke方法的返回值resultIAsyncResult result = delFunc.BeginInvoke(1, 2, null, null);//result.IsCompleted通过这个可以判断异步委托是否执行完成,执行完成返回true//if (!result.IsCompleted)//{//异步委托没有执行完成做点其他事情//}没有执行完,主线程就一直执行下面的循环体//while (!result.IsCompleted)//{//    Thread.Sleep(100);//    Console.WriteLine("Main thread working...");//    Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());//    Console.WriteLine();//}//2.调用委托的EndInvoke方法,把BeginInvoke方法的返回值result传入,即可拿到委托方法的执行结果string str = delFunc.EndInvoke(result);Console.WriteLine(str);IAsyncResult.IsCompleted 用于监视异步委托的执行状态(true / false),这里的时间是不定的,也就是说一定要等到异步委托执行完成之后,这个属性才会返回 true。通过一个循环,委托方法没有执行完成之前,让主线程做点其他事情,如下:while (!result.IsCompleted){Thread.Sleep(100);Console.WriteLine("Main thread working...");Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());Console.WriteLine();}

这样,如果异步委托的方法耗时较长,那么主线程会一直工作(循环执行)下去。

在委托方法中加上Thread.Sleep(3000);语句上面绿色底纹所示再次运行发现运行结果要等待一会才显示出来这说明EndInvoke()方法会阻塞当前线程直到异步委托方法执行完成之后才能继续往下执行

BeginInvoke()方法无法转到定义查看,因为它是编译生成时自动生成的方法, 是可以接受多个参数的,它的参数个数和参数类型取决于定义委托时的参数个数和类型,不过无论它有多少个参数,最后两个参数都是不变的。

上面是简单方式的异步委托。

还可以用下面的方法 WaitOne(),自定义一个等待的时间,如果在这个等待时间内异步委托没有执行完成,那么就会执行 while 里面的主线程的逻辑,反之就不会执行。

while (!result.AsyncWaitHandle.WaitOne(1000))//等1秒,1秒后异步委托没有执行完成才执行循环体
{Thread.Sleep(100);Console.WriteLine("Main thread working...");Console.WriteLine("Main thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString());Console.WriteLine();
}

4. 异步委托(带回调函数):

    下面看有回调函数的异步委托。

#region 有回调函数的异步委托
// //BeginInvoke方法倒数第二个参数为回调函数,
//最后一个参数传给回调函数的参数
//AsyncCallback
//第3个参数为AsyncCallback类型,转到定义发现也是一个委托,如下
//public delegate void AsyncCallback(IAsyncResult ar);
//据此我们就可以根据该委托定义一个回调函数,见下
delFunc.BeginInvoke(1, 2, MyAsyncCallback,"123");
#endregion
public static void MyAsyncCallback(IAsyncResult ar)
{Console.WriteLine("执行回调函数线程的ID:"+Thread.CurrentThread.ManagedThreadId);
}

输出:

       从结果可以看出,异步线程id与回调函数的ID是同一个。因为执行BeginInvoke方法时到线程池中取出一个有效线程去执行委托delFunc,然后该线程又去执行回调函数。执行过程如下图所示。

 

//回调函数是干什么用的?什么时候会被执行呢?
//回调函数:是异步委托方法执行完成之后,再来调回调函数,也就是说异步委托方法执行之后,还需要处理些事情就可以用回调函数来处理。//1.在回调函数中如何拿到异步委托执行的结果(前面讲过靠调用委托的EndInvoke方法,即可拿到委托执行的结果,所以关键是如何拿到异步委托)
public static void MyAsyncCallback(IAsyncResult ar)
{//1.1把回调函数的参数ar强转为实例类型AsyncResult result = (AsyncResult)ar;//1.2通过实例类型的AsyncDelegate属性拿到异步委托(实际就是delFunc),然后再强转为它的实际类型var del=(Func<int, int, string>)result.AsyncDelegate;//1.3通过del的EndInvoke方法,参数为ar的实例类型或者就为ar,就可以得到异步委托执行结果string returnvalue = del.EndInvoke(ar);Console.WriteLine(returnvalue);//2.如何拿到给回调函数的参数:利用ar.AsyncState或result.AsyncState属性Console.WriteLine("传给回调函数的参数:"+ar.AsyncState);//总结:以上拿到了异步委托的执行结果和传给回调函数的参数,在后续就可以做些其他处理。
当然还有更简单些的方法拿到异步委托执行结果和给回调函数的参数。办法是改造前面的BeginInvoke方法最后一个参数,设置为当前的异步委托(因为最后一个参数为object类型,所以可改为任何类型)//delFunc.BeginInvoke(1, 2, MyAsyncCallback, delFunc);//这样的话ar.AsyncState获取的就是异步委托var del= (Func<int, int, string>)ar.AsyncState;//接下来要获取返回值只要如下语句即可获取到执行异步委托的返回值string str= del.EndInvoke(ar);Console.WriteLine(str);Console.WriteLine("回调函数的ID:"+Thread.CurrentThread.ManagedThreadId);
}

 

 

 

本文根据徐照兴教授讲义编写,有些改动。


http://chatgpt.dhexx.cn/article/NM38WBEl.shtml

相关文章

Invoke and BeginInvoke

本文转自&#xff1a;http://www.cnblogs.com/worldreason/archive/2008/06/09/1216127.html 在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate&#xff0c;至于委托的本质请参考我的另一随笔&#xff1a;对.net事件的看法。 一、为什么Control类提供了Invoke和…

C# Thread Delegate MethodInvoker Invoke BeginInvoke 关系

异步调用是CLR为开发者提供的一种重要的编程手段&#xff0c;它也是构建高性能、可伸缩应用程序的关键。在多核CPU越来越普及的今天&#xff0c;异步编程允许使用非常少的线程执行很多操作。我们通常使用异步完成许多计算型、IO型的复杂、耗时操作&#xff0c;去取得我们的应用…

C#中Delegate/Control的Invoke/BeginInvoke/EndInvoke

目录 一、前言 二、背景 三、Delegate的Invoke/BeginInvoke/EndInvoke 1、基于[需求1] 1.1、直接在主线程中运行“耗时操作” 1.2、通过Thread将“耗时操作”放在子线程中运行 1.3、通过Delegate.BeginInvoke()将“耗时操作”放在子线程中运行 1.4、总结 2、基于[需求…

Invoke和BeginInvoke理解

在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate&#xff0c;至于委托的本质请参考我的另一随笔&#xff1a;对.net事件的看法。 一、为什么Control类提供了Invoke和BeginInvoke机制&#xff1f; 关于这个问题的最主要的原因已经是dotnet程序员众所周知的&…

C#的Invoke与BeginInvoke区别

【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别&#xff08;SamWang&#xff09; 今天无意中看到有关Invoke和BeginInvoke的一些资料&#xff0c;不太清楚它们之间的区别。所以花了点时间研究了下。 据msdn中介绍&#xff0c;它们最大的区别就是Be…

c# Invoke和BeginInvoke 区别详解

Control.Invoke 方法 (Delegate):在拥有此控件的基础窗口句柄的线程上执行指定的委托。 Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。 以下为实际应用中碰到的问题&#xff0c;在主线程中启动一个线程&#xff0c;然后在这个线程…

C# beginInvoke

摘要 异步这东西&#xff0c;真正用起来的时候&#xff0c;发现事情还是挺多的&#xff0c;最近在项目中用到了异步的知识&#xff0c;发现对它还是不了解&#xff0c;处理起来&#xff0c;走了不少弯路。觉得还是补一补还是很有必要的。 MSDN原文地址&#xff1a;https://ms…

[C#基础]c#中的BeginInvoke和EndEndInvoke

摘要 异步这东西,真正用起来的时候,发现事情还是挺多的,最近在项目中用到了异步的知识,发现对它还是不了解,处理起来,走了不少弯路。觉得还是补一补还是很有必要的。 MSDN原文地址:https://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.110).aspx 正文 .Net framewo…

C# BeginInvoke实现异步编程

C# BeginInvoke实现异步编程 BeginInvoke实现异步编程的三种模式&#xff1a; 1.等待模式 在发起了异步方法以及做了一些其他处理之后&#xff0c;原始线程就中断并且等异步方法完成之后再继续&#xff1b; eg&#xff1a; using System; using System.Collections.Generic;…

This.invoke和this.begininvoke的区别?

应用场景 在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke和BeginInvoke就是为了解决这个问题。 个人总结 ①This.begininvoke和this.invoke注册委托调用的方法都是等UI主线程执行到“windows消息泵”的时候才…

C#——invoke和begininvoke 区别

invoke和begininvoke 区别 一直对invoke和begininvoke的使用和概念比较混乱&#xff0c;这两天看了些资料&#xff0c;对这两个的用法和原理有了些新的认识和理解。 首先说下&#xff0c;invoke和begininvoke的使用有两种情况&#xff1a; 1. control中的invoke、begininvoke。…

C#Invoke和BeginInvoke应用详解

最近&#xff0c;在研究Invoke的使用&#xff0c;但是真的是一头雾水&#xff0c;网上看了很多资料&#xff0c;感觉还是看不懂&#xff0c;因为对于入门级的小白&#xff0c;想像不出Invoke的应用场景&#xff0c;更谈不上如何用了&#xff1f; 1、Invoke到底是什么&#xff…

Java工作流框架:探索流程引擎的实现和应用

目前&#xff0c;市面上有很多基于SpringBootVue前后端分离的Java快速开发框架和工作流开发框架可供选择。以下是一些比较流行的框架&#xff1a; 1. Spring Cloud&#xff1a;Spring Cloud是一套基于Spring Boot的开发工具&#xff0c;用于快速构建分布式系统中的服务。它利用…

Java工作流框架和应用场景

一&#xff1a;Java工作流框架是一种用于设计、执行和管理工作流程的技术。以下是几个常见的Java工作流框架&#xff1a; Activiti&#xff1a;Activiti是一款流行的开源Java工作流引擎&#xff0c;它基于BPMN 2.0标准&#xff0c;支持复杂的工作流程设计和管理。Activiti具有高…

工作流使用

#&#x1f33b; 工作流使用 无需开发代码&#xff0c;即可快速创建工作流、表单&#xff0c;并完成审批、监控等操作。 #功能脑图 #特点 基于 Flowable&#xff08;Activiti&#xff09;生来具有的稳定工作流引擎。使用flowable官方流程设计器&#xff0c;功能强大&#xff…

工作流 开源(java工作流框架jbpm)

工作流(工作流) :“在部分或整个业务流程的计算机应用环境中实现自动化” l简单来说&#xff0c;就是用程序管理工作流程&#xff0c;以表格审核和任务处理为主体&#xff0c;实现办公室自动化 工作流帮助器管理业务流程&#xff0c;业务操作保持不变。 工作流是通知流程&…

java工作流开源框架可以提高工作效率吗?

要想回答这个问题&#xff0c;就需要了解什么是java工作流开源框架&#xff0c;以及java工作流开源框架的主要特点是什么。随着大数据时代的拓展发展&#xff0c;低代码开发平台已经在数字化管理时代中深受欢迎&#xff0c;是做好数据管理和提升企业数字化发展步伐的重要工具。…

Java开源 开源工作流

Willow 点击次数&#xff1a;18942 由Huihoo Power开发详细可到其中文主页查看。 OpenWFE 点击次数&#xff1a;17672 OpenWFE是一个开放源码的Java工作流引擎。它是一个完整的业务处理管理套件&#xff1a;一个引擎&#xff0c;一个工作列表&#xff0c;一个Web界面和一个…

Java实现自定义工作流

这篇文章实现java自定义工作流程&#xff0c;对工作流不太熟悉的可以先看下工作流相关文章&#xff1a; 工作流 相关表结构、实体创建 流程主表&#xff1a;tbl_workflow_requestbase&#xff08;这里以项目工地工作流为例&#xff09; CREATE TABLE tbl_workflow_requestba…

JAVA工作流的优雅实现方式

今天查找线上问题&#xff0c;看到一个让我脑洞大开的工作流实现方式。以前用过责任链模式&#xff0c;也用过模板模式实现类工作流的方式&#xff0c;但是对比这个工具&#xff0c;逊色不少&#xff0c;不卖关子了&#xff0c;就是Apache Commons Chain&#xff0c;它是Comman…