简体   繁体   English

C#SocketAsyncEventArgs停止触发完成的事件

[英]C# SocketAsyncEventArgs stops firing completed event

I have noticed a problem where the .Completed event of a SocketAsyncEventArgs seems to stop firing . 我注意到一个问题,其中SocketAsyncEventArgs的.Completed事件似乎停止触发 The same SAEA can fire properly and be replaced in the pool several times, but eventually all instances will stop firing, and because the code to replace them in the pool is in the event handler, the pool empties. 相同的SAEA可以正确触发并在池中多次替换,但是最终所有实例都将停止触发,并且由于在池中替换它们的代码在事件处理程序中,因此池为空。

The following circumstances are also apparently true: 以下情况显然也是正确的:

1) It seems to only occur when a server side socket sends data out to one of the connected clients. 1)似乎仅在服务器端套接字将数据发送到所连接的客户端之一时才会发生。 When the same class is connecting as a client, it doesn't appear to malfunction. 当同一类作为客户端连接时,它似乎没有故障。

2) It seems to occur under high load. 2)它似乎在高负载下发生。 The thread count seems to creep up until eventually the error happens. 线程数似乎一直在增加,直到最终发生错误为止。

3) A test rig under similar stress appears never to malfunction. 3)在类似压力下的测试设备似乎永远不会出现故障。 (It's only 20 messages per second, and the test rig has been proven to 20K) (每秒只有20条消息,并且测试装备已被证明可以达到20K)

I'm not going to be able to paste the rather complicated code, but here is a description of my code : 我将无法粘贴相当复杂的代码,但这是我的代码说明

1) The main inspiration is this: http://vadmyst.blogspot.ch/2008/05/sample-code-for-tcp-server-using.html . 1)主要的灵感是这样的: http : //vadmyst.blogspot.ch/2008/05/sample-code-for-tcp-server-using.html It shows how to hook up a completion port using an event, how to get different sized messages over the TCP connection, and so on. 它显示了如何使用事件连接完成端口,如何通过TCP连接获取大小不同的消息,等等。

2) I have a byte buffer in which all SAEAs have a piece, that doesn't overlap. 2)我有一个字节缓冲区,其中所有SAEA都有一个不重叠的部分。

3) I have an object pool of SAEAs, based on a blockingcollection. 3)我有一个基于阻塞集合的SAEA对象池。 This throws if the pool is empty for too long. 如果池为空的时间太长,则会引发此错误。

4) As a server, I keep a collection of sockets returned from the AcceptAsync function, indexed by the endpoint of the client. 4)作为服务器,我保留了从AcceptAsync函数返回的套接字的集合,该集合由客户端的端点索引。 A single process can use one instance as a server as well as multiple instances as clients (forming a web). 单个进程可以将一个实例用作服务器,也可以将多个实例用作客户端(形成Web)。 They share the data buffer and pool of SAEAs. 它们共享SAEA的数据缓冲区和池。

I realise it's hard to explain this; 我知道很难解释这一点。 I've been debugging it for an entire day and night. 我整天都在调试它。 Just hoping someone has heard of this or has useful questions or suggestions. 只是希望有人听说过或有有用的问题或建议。

At the moment, I am suspecting some sort of thread exhaustion, leading to the SAEAs not being able to call the completion. 目前,我怀疑某种线程耗尽,导致SAEA无法调用完成。 Alternatively, some sort of buffer problem on the outgoing buffer. 或者,在传出缓冲区上出现某种缓冲区问题。

So, another day of debugging and finally I have an explanation. 因此,调试的另一天,最后我得到了解释。

1) The SAEAs were not firing the completed event because they were unable to send more. 1)SAEA无法发送已完成的事件,因为它们无法发送更多消息。 This is revealed by Wireshark to be due to the TCP window emptying. Wireshark揭示这是由于TCP窗口为空。 (TCP ZeroWindow) (TCP ZeroWindow)

2) The TCP window was emptying because the networking layer was passing an event up the stack that took too long to complete, ie there's no producer/consumer between the network layer and the UI. 2)TCP窗口正在清空,因为网络层正在向上传递一个事件,该事件花费了太长时间才能完成,即网络层和UI之间没有生产者/消费者。 Thus the network op would have to wait for the screen draw before sending the ACK. 因此,网络op必须在发送ACK之前等待屏幕绘制。

3) The event that took too long was a screen draw in an event handler on the GUI. 3)花了太长时间的事件是GUI上事件处理程序中的屏幕绘制。 The test rig was a console window (one that summarized incoming messages), so that's why it didn't cause a problem at much higher load. 测试平台是一个控制台窗口(一个汇总传入消息的窗口),因此这就是为什么它在高得多的负载下不会引起问题的原因。 It's normal not to redraw the screen on each message, but this was happening because the project isn't quite done yet. 通常不要在每条消息上重画屏幕,但这是发生的,因为该项目尚未完成。 The redraw rate would have been fixed later. 重提率将在以后确定。

4) The short term solution is simply to make sure there's no GUIs holding up the show. 4)短期解决方案只是确保没有GUI阻止演出。 A more robust solution might be to create a producer/consumer at the network layer. 一个更强大的解决方案可能是在网络层创建生产者/消费者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM