C#异步行为旧模型之——APM

几种异步编程模式:APM【.net 1.0出现】、EAP【.Net 2.0引入的】、TAP【4.0引入,现在推荐的用法】

历史异步模式已经被淘汰,不推荐使用,但是了解它的思想有助于知道最新模式的优势和来历曲折和来之不易,这样的东西才更知道珍惜,让我们更有动力去学习。

APM模式:
.net 1.0时期就提出的一种异步模式,并且基于IAsyncResult接口实现BeginXXX和EndXXX类似的方法。
.net中有很多类实现了该模式(比如HttpWebRequest,FileStream类中提供了BeginRead和EndRead来对文件进行异步字节读取操作。)
委托的三个方法:

 

 

 

  1. Invoke() 调用时,会阻塞当前线程,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念。
  2. BeginInvoke() 调用时,当前线程会启用线程池中的某个线程来执行此方法,当前线程不被阻塞,继续运行后面的代码,表现出“异步”的概念。
  3. EndInvoke() ,在想获取 BeginInvoke() 执行完毕后的结果时,调用此方法来获取。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用未完成,EndInvoke 将一直阻塞到异步调用完成。

 

 

 

 但是APM模型也存在一些缺点:

1、若不使用回调机制,则需等待异步操作完成后才能继续执行,此时未达到异步操作的效果。
2、在异步操作的过程中,无法取消,也无法得知操作进度。
3、若编写GUI程序,异步操作内容与主线程未在同一线程,操作控件时会引起线程安全问题。
为了解决这些缺陷,微软推出了其他的异步模式,预知后事如何,且听下回分解。

▲BeginInvoke和EndInvoke

 

 

 


BeginInvoke 方法启动异步调用。 该方法具有与你要异步执行的方法相同的参数,另加两个可选参数

 

 

 

 

  AsyncCallback类型的参数,它是一个委托,实际上就是定义了回调函数,
  此委托引用在异步操作完成时调用的方法。由于回调函数内部调用EndInvoke函数,所以也需要IAsyncResult参数
▲1、等待一直到完成模式

 

 

 

▲ 2、IAsyncResult.AsyncWaitHandle.WaitOne模式
使用 WaitHandle 属性获取 IAsyncResult.AsyncWaitHandle ,使用它的 WaitOne 方法阻止执行,直到 WaitHandle 收到信号,然后调用 EndInvoke。
▲IAsyncResult

 

 

  当异步调用完成时 WaitHandle 会收到信号,而你可以通过调用 WaitOne 方法来等待它
  当对用于执行异步方法调用的委托调用 EndInvoke 时,不会自动关闭等待句柄。 如果释放对等待句柄的所有引用,则当垃圾回收功能回收此等待句柄时将释放系统资源。 若要在使用完等待句柄后立即释放系统资源,请调用 WaitHandle.Close 方法。 当显式关闭或释放可释放对象时,垃圾回收的工作效率更高。
  WaitOne、WaitAll、WaitAny都会阻塞当前线程,直到异步完成。
注意
  AsyncWaitHandle 属性中包含的 WaitHandle 可用于阻止当前线程,直到异步调用完成。 但是,如果在 BeginInvoke 调用期间指定了 WaitHandle,则将忽略 AsyncCallback。 因此,当应用程序在执行完 AsyncCallback 之前关闭,即使 WaitHandle 用于阻止,直到异步调用完成。 有关这种情况的示例,请参阅 AsyncResult 类的示例,并删除 Thread.Sleep 语句。

 

 

▲3、轮询模式
——IAsyncResult.IsCompleted检查是否异步方法是否完成

 

 

▲4、回调模式——回调函数,异步方法结束后执行回调方法。
1、回调方法,与AsyncCallback委托一致

2、回调方法内调用EndInvoke获取异步执行的返回结果【如果委托有返回值是Func<>】

 

 

 

 警告 始终在异步调用完成后调用 EndInvoke。

 

本文作者:好Wu赖

本文链接:https://www.cnblogs.com/erlongxizhu-03/p/12973124.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   好Wu赖  阅读(306)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起