7

是否可以在 .NET 的异步回调中进行繁重的处理,在返回之前将它们占用几秒钟?还是我剥夺了操作系统/重要资源的运行时?

例如,考虑TcpListener.BeginAcceptSocket. 我的回调从调用 开始EndAcceptSocket,然后花一段时间接收数据,然后才关闭套接字并返回。这是它的使用方式,还是我希望在我自己的线程上进行额外的处理?

4

2 回答 2

1

是的,这就是异步套接字(Tcp 客户端、侦听器等)的使用方式。您应该始终确保调用 end aysnc 方法,然后执行您想要的任何处理。不调用 EndAccept()、EndSEnd()、EndReceive() 等方法可能会导致内存泄漏,因此遵循此方法始终是一个好习惯。

使用的线程与您自己手动设置后台线程没有什么不同,并且实际上设计用于几秒钟的“长期操作”。相信我,您不希望在调度或 GUI 线程上运行任何需要很长时间的东西。

我有超过 90 个基于移动的系统,它们使用异步套接字与服务器通信,它做得非常好:比 Web 服务快得多(记住所有 Web 协议都在 Socket 之上运行),易于检测错误等,等等

我在我的服务器代码上做同样的事情(与其他一些用于中间件和后端通信的 WCF 混合在一起),它是我们使用过的最可扩展的通信。您必须在 Google 上对其进行搜索,但是有一个人使用该技术发布了他的测试,他能够支持 1,000 个并发通信到只有 11 个线程的服务器。不错。

来自 MS 的服务器示例:http: //msdn.microsoft.com/en-us/library/fx6588te.aspx

来自 MS 的客户端示例:http: //msdn.microsoft.com/en-us/library/bew39x2a.aspx

让它“完美”需要的不仅仅是这些,但这是一个很好的起点。

于 2011-01-11T03:33:31.127 回答
1

我重复了一篇关于该主题的 CodeProject 文章的实验,发现 .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
总计 = 50542073

使用 10 个线程池工作项

T0 = 23335890
T1 = 20998989
T2 = 22920781
T3 = 9802624
T4 = 0
T5 = 0
T6 = 0
T7 = 0
T8 = 0
T9 = 0
总计 = 77058284

请注意,在 1 秒的时间片中实际执行的 10 个线程池工作项中只有 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
总计 = 64328883
于 2011-01-14T06:12:08.627 回答