关于IAsyncResult接口的CompletedSynchronously属性

简介: IAsyncResult大伙都用的多吧,在异步编程的时候,我们通常根据它的IsCompleted属性来判断异步操作是否已完成。不过该接口还有另外一个属性CompletedSynchronously,MSDN的解释一如既往的简单(查阅MSDN的时候,往往能看懂它的文字,不理解它的意思,有同感的朋友举手。

IAsyncResult大伙都用的多吧,在异步编程的时候,我们通常根据它的IsCompleted属性来判断异步操作是否已完成。不过该接口还有另外一个属性CompletedSynchronously,MSDN的解释一如既往的简单(查阅MSDN的时候,往往能看懂它的文字,不理解它的意思,有同感的朋友举手。):获取异步操作是否同步完成的指示。

异步操作,同步完成,到底啥意思呢。假如我是IAsyncResult接口的实现者,我该如何设置何时设置CompletedSynchronously的值呢?假如我是IAsyncResult接口实现类的使用者,CompletedSynchronously对于我来说又有什么用呢?以下是我个人看法,若有错误,欢迎拍砖。

假设我们自定义的类需要实现某个耗费时间可能长可能短的功能,时间长短并不受代码控制,比如获取某个资源进行操作,请求资源时经常需要排队,偶尔又能马上取得。

 1 public class CompletedSynchronouslyShow
 2 {
 3     int _blockInterval = new Random().Next(0, 10000);
 4 
 5     /// <summary>
 6     /// 为了更好地说明问题,我们将该方法定义成有返回值
 7     /// </summary>
 8     /// <returns>执行是否成功</returns>
 9     public bool DoSth()
10     {
11         //模拟真实情形,阻塞不定时间
12         System.Threading.Thread.Sleep(_blockInterval);
13 
14         //其它操作
15         return true;
16     }
17 }

 为了不阻塞当前线程,我们需要使用异步方式比如new Thread(Show.DoSth).Start()来开启新线程调用DoSth(Show为CompletedSynchronouslyShow类型的对象)。众所周知,虽然硬件性能步步高升,但开启并维护一个新线程对系统来说还是一件体力活。如果阻塞的时间并不久,我们希望仍然在当前线程执行DoSth方法。由于阻塞时间只能在DoSth方法内部做判断,因此上述愿望的实现不能期望调用方,不论异步还是同步,调用方调用的只能是同一个方法。既然是同一个方法,那么方法的返回值不能是原先的返回值(这里是布尔型),一般情况下IAsyncResult是最合适的(我们也可以自定义返回类型,只要能满足要求)。而IAsyncResult接口的CompletedSynchronously属性正是指示方法执行完成时所在的线程是否就是调用线程

下面是修改后的代码:

 1 public class CompletedSynchronouslyShow
 2 {
 3     int _blockInterval = new Random().Next(0, 10000);
 4 
 5     /// <summary>
 6     /// 为了更好地说明问题,我们将该方法定义成有返回值
 7     /// </summary>
 8     /// <returns>执行是否成功</returns>
 9     private bool DoSth()
10     {
11         //模拟真实情形,阻塞不定时间
12         System.Threading.Thread.Sleep(_blockInterval);
13 
14         //其它操作
15         return true;
16     }
17 
18     //客户端调用该方法而不是DoSth方法
19     public IAsyncResult BeginDoSth(AsyncCallback callback = null, object state = null)
20     {
21         return new AsyncResult(_blockInterval, new Func<bool>(DoSth), callback, state);
22     }
23 }
24 
25 public class AsyncResult : IAsyncResult
26 {
27     private Func<bool> _doSth;
28     private AsyncCallback _callback;
29 
30     public bool Result { get; private set; }
31 
32     private bool _completedSynchronously;
33     public bool CompletedSynchronously
34     {
35         get { return _completedSynchronously; }
36     }
37 
38     private bool _isCompleted;
39     public bool IsCompleted
40     {
41         get { return _isCompleted; }
42     }
43 
44     private object _state;
45     public object AsyncState
46     {
47         get { return _state; }
48     }
49 
50     public AsyncResult(int blockInterval, Func<bool> doSth, AsyncCallback callback, object state)
51     {
52         _doSth = doSth;
53         _state = state;
54         _callback = callback;
55         //小于3秒直接返回值
56         if (blockInterval < 3000)
57         {
58             Result = doSth();
59             //_completedSynchronously设为true表示同步执行
60             this._completedSynchronously = this._isCompleted = true;
61             if (_callback != null)
62             {
63                 _callback(this);
64             }
65         }
66         else
67         {
68             doSth.BeginInvoke(new AsyncCallback(SetResult), null);
69             70         }
71     }
72 
73     private void SetResult(IAsyncResult ar)
74     {
75         Result = _doSth.EndInvoke(ar);
76         if (_callback != null)
77         {
78             _callback(this);
79         }this._isCompleted = true;
80     }
81 }

恩,少年们于是又不淡定了:这不是玩我呢吧,这都啥玩意。上述代码核心在于实现了IAsyncResult接口,通过它我们才能展开后续工作。这里说明CompletedSynchronously属性的意义:BeginDoSth方法给人一种异步的错觉,但它同时兼有异步和同步的特性,由CompletedSynchronously属性区分。它还体现了一种编程模式,该模式在.Net框架中很多地方都在使用,比如WCF输出信道接口IOutputChannel:

1 public interface IOutputChannel
2 {
3      IAsyncResult BeginSend(Message message, AsyncCallback callback, object state);
4      void EndSend(IAsyncResult result);
5 }

很多具有异步操作的类型都有类似BeginXX和EndXX成对出现的方法,参数也大同小异。EndXX的作用同委托的EndInvoke方法一样,可供回调函数使用,当我们需要获取操作的返回值时,在回调函数中一般要调用该方法。

作为IAsyncResult接口实现方,CompletedSynchronously一般设为false即可,一个原因是判断何时采用同步方式合适采用异步方式(如例子中获取阻塞时间)在大多数情况下并不容易。我觉得在资源请求、Stream操作等方面可以考虑这个问题。网络通信中,Socket.BeginSendTo方法就可能返回CompletedSynchronously为true的对象,它是按照什么来作为设置的依据,我反射了代码,也查不出一个所以然,我只好猜测它是根据发送字节总数和单次最大发送字节数比较结果选择是否发送方式(同步or异步)。

有时候CompletedSynchronously属性似乎并不像它本身意思,更多的是“数据是否完整”(多次异步操作数据流会引出这个概念)。我是看Async Programming Model - Reloaded一文得出这个结论的,该文说道web响应流BeginRead返回对象若CompletedSynchronously为true,则说明web响应流已经全部接收完毕,此时应该使用Read同步方法。我觉得该说法有误,既然BeginRead返回的CompletedSynchronously已经为true,说明BeginRead执行在当前线程,那么后续执行也应该是当前线程,从这么方面来说它和Read方法是一样的,可能在其它方面会有损耗(比如构造IAsyncResult对象)。另一方面,若真如该文所说,那么即使某次BeginRead读取的字节已经是接收到本地的,但由于数据并未全部接收完,所以该次BeginRead返回的CompletedSynchronously仍为false。不论如何,真相只有一个,留待以后验证,有知道的朋友希望不吝赐教,感激不尽。

转载请注明本文出处:http://www.cnblogs.com/newton/archive/2012/11/30/2795614.html

目录
相关文章
|
9月前
|
计算机视觉
YOLOv11改进策略【卷积层】| 2024最新轻量级自适应提取模块 LAE 即插即用 保留局部信息和全局信息
YOLOv11改进策略【卷积层】| 2024最新轻量级自适应提取模块 LAE 即插即用 保留局部信息和全局信息
407 0
YOLOv11改进策略【卷积层】| 2024最新轻量级自适应提取模块 LAE 即插即用 保留局部信息和全局信息
|
安全 算法 Java
CAS是"Compare and Swap"(比较并交换)
CAS是"Compare and Swap"(比较并交换)的缩写,是一种多线程同步的原子操作。它基于硬件的原子性保证,用于解决并发环境下的数据竞争和线程安全问题。
303 0
|
存储 安全 算法
无线加密技术的种类、工作原理
【4月更文挑战第22天】
548 0
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
632 0
|
供应链 物联网 网络安全
跨境电商国外研究现状如何
跨境电商研究涵盖四大领域:发展趋势与模式、影响因素、消费者行为及挑战与问题。研究发现,全球化供应链整合、平台全球化拓展、社交电商兴起和技术应用创新是主要趋势。影响因素包括技术、政策、市场环境和人才。消费者行为受购买决策因素、文化差异和信任问题影响。挑战主要包括关税与税收、物流配送、标准规范缺失及网络安全与隐私保护问题。
|
Web App开发 JavaScript 前端开发
浏览器内小脚本开发
【8月更文挑战第31天】
400 1
|
人工智能 自然语言处理
华为GTS LocMoE+:高可扩展性亲和度 MoE 架构,低开销实现主动路由
【8月更文挑战第6天】华为GTS提出LocMoE+,一种高可扩展性Mixture-of-Experts架构,通过亲和度路由策略高效分配任务,自适应调整专家容量优化资源利用,并采用通信优化技术减少开销,实现在保证性能的同时大幅提升训练效率和推理速度,尤其在多节点集群环境下优势明显。
292 1
|
存储 弹性计算 安全
阿里云4核16G配置云服务器收费标准及新老用户优惠价格整理与参考
阿里云服务器4核16G配置支持按量(小时)付费和按月付费及按年付费,根据小编查询的结果,目前按量付费收费标准最低0.8元每小时,按月收费最低收费标准为384.0元1个月,实际购买中,新老用户均可通过阿里云活动下单购买,新用户最低优惠价格为1710.00元1年,老用户最低优惠价格为3489.00元1年,下文是阿里云服务器4核16G配置最新收费标准及新老用户优惠价格。
924 0
阿里云4核16G配置云服务器收费标准及新老用户优惠价格整理与参考
|
算法 固态存储 架构师
【最佳实践】一文掌握并应用Elasticsearch中的GC实现垃圾日志处理
你是否了解 GC 日志?以及如何通过GC,来解决何时找到、何时处理以及如何处理垃圾日志?
2899 0
【最佳实践】一文掌握并应用Elasticsearch中的GC实现垃圾日志处理
|
存储 搜索推荐 数据挖掘
PDS(Personal/Enterprise Data Storage)
PDS 是一款集数据存储、管理和智能分析于一体的云存储平台,适用于个人和企业用户。它提供了目录、文件管理功能,以及影像内容的分类打标、人脸聚类等智能分析功能,基于内容的智能搜索能力,用户体系以及第三方身份系统接入能力。用户可基于此开发一套面向企业或个人的网盘系统。PDS 还提供了一些官方应用,可与您的系统组合使用,简化您的开发。
767 2