博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#之异步编程
阅读量:2756 次
发布时间:2019-05-13

本文共 3190 字,大约阅读时间需要 10 分钟。

微软提供了大量的异步API供我们使用,比如网络api,http协议的api等等,十分方便。在熟练掌握异步编程之后,我尝试自己写一个异步库,主要是tcp网络通信方面的,协议是私有协议,我在私有协议的基础上再封装一层供应用层调用。

但是我发现问题没那么简单,其他的都比较简单,task 之类,难点在一个地方:

请求------------------------------》网络等待----------------------------》网络应答-----------------------》协议解析---------------应用层处理

这里有一个等待的过程,我需要等待 等待 再等待。如何去等待?

开始我想到了信号量,于是就如下代码:

if(msg._autoResetEvent.WaitOne(m_iWaitTime))                {                    if (GetResult(msg.Seq, out ShamResponseMsg outMsg))                    {                        sg.FromIp = outMsg.FromIp;                        sg.FromPort = outMsg.FromPort;                        sg.Result = outMsg.Result;                        sg.Xml = outMsg.Xml;                        sg.MsgId = outMsg.MsgId;                    }                    else                    {                        sg.Result = ShamResult.NoResult;                    }                }

等待网络应答完,在接下来处理。开始用着来也没觉得有什么异常。

某天,大规模并发过来之后,发现我的等待把net的线程池阻塞住了,其他依赖线程池的功能都无法正常工作了。

我表示难道就没有其他的好的等待的方法么?只能用信号量吗?幸好,net4.5是开源的,我想去看看他内部如何使用http的异步的,终于被我找到了谜底。

TaskCompletionSource TaskCompletionSource TaskCompletionSource 这个类就是微软为我们创造出来的异步等待,他不会堵塞当前线程,等收到应答后,又能自动切换回来。

接下来,就研究这个类如何使用,我就抄一段msdn上面的例子,供大家学习和参考。

static void Main()    {        TaskCompletionSource
tcs1 = new TaskCompletionSource
(); Task
t1 = tcs1.Task; // Start a background task that will complete tcs1.Task Task.Factory.StartNew(() => { Thread.Sleep(1000); tcs1.SetResult(15); }); // The attempt to get the result of t1 blocks the current thread until the completion source gets signaled. // It should be a wait of ~1000 ms. Stopwatch sw = Stopwatch.StartNew(); int result = t1.Result; sw.Stop(); Console.WriteLine("(ElapsedTime={0}): t1.Result={1} (expected 15) ", sw.ElapsedMilliseconds, result); // ------------------------------------------------------------------ // Alternatively, an exception can be manually set on a TaskCompletionSource.Task TaskCompletionSource
tcs2 = new TaskCompletionSource
(); Task
t2 = tcs2.Task; // Start a background Task that will complete tcs2.Task with an exception Task.Factory.StartNew(() => { Thread.Sleep(1000); tcs2.SetException(new InvalidOperationException("SIMULATED EXCEPTION")); }); // The attempt to get the result of t2 blocks the current thread until the completion source gets signaled with either a result or an exception. // In either case it should be a wait of ~1000 ms. sw = Stopwatch.StartNew(); try { result = t2.Result; Console.WriteLine("t2.Result succeeded. THIS WAS NOT EXPECTED."); } catch (AggregateException e) { Console.Write("(ElapsedTime={0}): ", sw.ElapsedMilliseconds); Console.WriteLine("The following exceptions have been thrown by t2.Result: (THIS WAS EXPECTED)"); for (int j = 0; j < e.InnerExceptions.Count; j++) { Console.WriteLine("\n-------------------------------------------------\n{0}", e.InnerExceptions[j].ToString()); } } //tt5(); Console.ReadKey(); }

重点总结:

使用这个类的TaskCompletionSource 的等待不会堵塞线程池的当前线程,可以保证线程池的正常工作,应对大规模的并发。 

 

 

转载地址:http://kmvad.baihongyu.com/

你可能感兴趣的文章
重构初体验
查看>>
软件设计经典书籍推荐
查看>>
信息检索及信息过滤方法概述
查看>>
suggestTree-实现rank-ordered autocomplete suggestions的数据结构
查看>>
LSH: Locality Sensitive Hashing Theory
查看>>
C++容器模板在共享内存中的使用
查看>>
SHA1和MD5算法详解和源码
查看>>
URL短地址压缩算法 微博短地址原理解析 (Java实现)
查看>>
proxy
查看>>
新浪微博布局学习——妙用TabHost
查看>>
ActivityGroup相关--getLocalActivityManager() 以及intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)用法
查看>>
android 拍照上传及本地上传
查看>>
ANSI、unicode、utf-8、DBCS等字符集及相关数据类型、函数的区别
查看>>
Android 更新UI的两种方法——handler和runOnUiThread()
查看>>
详解Android中AsyncTask的使用
查看>>
从拉马努金到张益唐——数学是一个整体
查看>>
动态规划——最优二叉查找树
查看>>
Filtering ListView with custom (object) adapter
查看>>
onWindowFocusChanged重要作用 and Activity生命周期
查看>>
不再依赖A*,利用C++编写全新寻路算法
查看>>