可以在.NET的异步回调中进行大量处理,在返回之前将它们占用多秒钟吗?或者我是否剥夺了操作系统/重要资源的运行时间?
例如,考虑TcpListener.BeginAcceptSocket
。我的回调开始于调用EndAcceptSocket
,然后花费一段时间接收数据,然后才关闭套接字并返回。这是用于它的方式,还是我希望在我自己的线程上进行额外的处理?
答案 0 :(得分:1)
是的,这是异步套接字(Tcp客户端,监听器等)的设计使用方式。您应始终确保调用end aysnc方法,然后执行所需的任何处理。不调用EndAccept(),EndSEnd(),EndReceive()等等方法可能会导致内存泄漏,因此遵循这个方法总是很好。
使用的线程与您自己手动假脱机后台线程没有什么不同,并且实际上被设计用于甚至几秒钟的“长期操作”。相信我,你不希望在调度或GUI线程上运行那么长时间。
我有超过90个基于移动的系统,它们使用异步套接字进行服务器的通信,它做得非常好:比Web服务快得多(记住所有的Web协议都在Socket上运行),易于检测错误,等等。
我在我的服务器代码上做了同样的事情(与其他一些WCF混合用于中间件和后端通信部件),这是我们使用过的最具规模的通信。你必须在谷歌上做一个谷歌,但有一个人使用这项技术发布他的测试,他能够支持1,000个并发通信到一个只有11个线程的服务器。还不错。
MS的服务器示例:http://msdn.microsoft.com/en-us/library/fx6588te.aspx
来自MS的客户端示例:http://msdn.microsoft.com/en-us/library/bew39x2a.aspx
要让它“完美”需要更多时间,但这是一个很好的起点。
答案 1 :(得分:1)
我重复了CodeProject article on this topic的实验,发现.NET 4的结果与2003年描述的类似。请注意,文章实际上没有列出有问题的部分的结果,但据我了解它的主要问题仍然存在。
我重复使用CodeProject文章中的代码 - 只需下载它以自行运行此测试或进行实验。
测试将尝试使用10个并行线程在1秒内尽可能高的数量。
使用10个后台主题(即new Thread()
)
T0 = 4451756 T1 = 4215159 T2 = 5449189 T3 = 6244135 T4 = 3297895 T5 = 5302370 T6 = 5256763 T7 = 3779166 T8 = 6309599 T9 = 6236041 Total = 50542073
使用10个ThreadPool工作项
T0 = 23335890 T1 = 20998989 T2 = 22920781 T3 = 9802624 T4 = 0 T5 = 0 T6 = 0 T7 = 0 T8 = 0 T9 = 0 Total = 77058284
请注意,在1秒的时间片中,只有4个线程池工作项实际执行过!这是在四核CPU上,因此每个核心有一个线程。在前四个完成后执行的其他任务因为分配的1秒已经过期,他们没有增加他们的计数器。
这里的结论:有长任务,ThreadPool会让一些任务等待其他任务!因此,我强烈建议不要在ThreadPool任务中进行任何长处理(例如异步完成处理程序)。否则,如果您的数据处理占用CPU,您可能会保留更多重要的异步调用,或者如果只有一些任务进行大量处理,您可能会有非常不稳定的性能。
使用文章
中的自定义ThreadPool实现T0 = 7175934 T1 = 6983639 T2 = 5306292 T3 = 5078502 T4 = 3279956 T5 = 8116320 T6 = 3262403 T7 = 7678457 T8 = 8946761 T9 = 8500619 Total = 64328883