System.InvalidOperationException was thrown when sending data with EasyClient
I was using the easy client to send some data.
The source data was pushed into the application from about 20 incoming TCP connections, processed by a AppServer of SocketEngine, which called an EasyClient to send data to another place.
The client was under a pretty low workload, sending about 2 packages a second only. However, it occasionally threw a "System.InvalidOperationException" and the application became unusable afterward.
The following was the stack trace related to the exception. I could not found a line relative to my own code, I deduced that it was in another thread, spawned from the EasyClient.
System.InvalidOperationException: "An asynchronous socket operation is already in progress using this SocketAsyncEventArgs instance.";
SuperSocket.ClientEngine.AsyncTcpSession.SetBuffer(ArraySegment`1 bufferSegment) @ SuperSocket.ClientEngine\Core\AsyncTcpSession.cs[36:13]
SuperSocket.ClientEngine.ClientSession.SuperSocket.ClientEngine.IBufferSetter.SetBuffer(ArraySegment`1 bufferSegment) @ SuperSocket.ClientEngine\Core\ClientSession.cs[207:13]
SuperSocket.ClientEngine.EasyClientBase.OnSessionDataReceived(Object sender, DataEventArgs e) @ SuperSocket.ClientEngine\EasyClientBase.cs[236:13]
SuperSocket.ClientEngine.AsyncTcpSession.ProcessReceive(SocketAsyncEventArgs e) @ SuperSocket.ClientEngine\Core\AsyncTcpSession.cs[89:13]
Do you have a test case I can reproduce this issue?
Thank you for replying. It was hard to reproduce in a short time. I was trying to mock up a stress test model to reproduce this issue and I would post it here when it is finished. Meanwhile, I moved the application to another machine and see whether it would occur there as well.
And which version do you use?
Sorry to have forgotten to mention the versions. All assemblies were compiled from the newest source code from your repositories. I'd removed the dependency from NuGet and used the compiled assemblies in the ClientEngine project.
The projects targeting .NET 4.0 were used to compile the assemblies. And the operating system was Windows Server 2008.
I studied the source code of EasyClientBase and AsyncTcpSession.
I found that the AsyncTcpSession.SendInternal, AsyncTcpSession.StartReceive and AsyncTcpSession.SetBuffer can be using the same instance of SocketAsyncEventArgs without locking. However, the SocketAsyncEventArgs internally excludes data-sending, data-receiving and buffer-setting operations mutually. Those three operations can not proceed at the same time.
Consequently, the SetBuffer method can fail when the Socket is using the SocketAsyncEventArgs instance to receive or send data and therefore the InvalidOperationException is thrown.
Thread synchronization shall be deployed to avoid the above problem.
I think send and receive have different SocketAsyncEventArgs instances: private SocketAsyncEventArgs m_SocketEventArgs; private SocketAsyncEventArgs m_SocketEventArgsSend;
The issue happened to my applications when the client was attempting to receive data.
Could it be possible that the SetBuffer method was called when a socket was using the same SocketAsyncEventArgs instance to receive data?
Is there a way to produce this issue easily?
Not so easy, I am afraid. But, I will still try to make a test case for you, or fix this issue at my side and commit a pull request here if I am lucky.
重连多次,大概10次左右。
protected override void SetBuffer(ArraySegment
if (m_SocketEventArgs != null)
{
m_SocketEventArgs.SetBuffer(bufferSegment.Array, bufferSegment.Offset, bufferSegment.Count);
}
}
m_SocketEventArgs.SetBuffer 这里报这个错误。连接上之后,已经在接收数据时候,报错。