SocketAsyncEventArgs - 如何检测正在进行的套接字操作&终止?

时间:2017-06-09 15:56:48

标签: c# sockets

我有时会收到此错误:

  

使用此SocketAsyncEventArgs实例正在进行异步套接字操作。

...当我尝试拨打SocketServiceEventArgs.SetBuffer()

我意识到这是因为一个实例只能执行一个操作而且必须在使用中。但是我再次调用它是因为在客户端之前的超时之后,我希望尝试重新发送请求。我不想关闭这个套接字并使用新的套接字,因为那时连接将被客户端破坏。

但是,我需要做的是在执行此操作之前检查是否有其他操作正在进行中,如果是,请终止它,以便我可以再次发送。

我用来发送的代码是

saeaCommunicationObject.AcceptSocket.SendAsync(saeaCommunicationObject)

但更有可能正在进行的是接收

saeaCommunicationObject.AcceptSocket.ReceiveAsync(saeaCommunicationObject))

saeaCommunicationObjectSocketAsyncEventArgs)。

在研究中,我遇到过

AcceptSocket.EndReceive(IAsyncResult asyncResult)

但我不确定这是否正确,而且我也不知道在哪里获得asyncResult(所以如果这是正确的,我的问题是,这应该来自哪里?)

那么我该怎么做才能检查它是否在进行中(如果是,则终止它)?

修改

我看过一个地方建议(但不建议)使用P / Invoke使用CancelIoEx() - 但是我无法解决这个问题,而且这方面的文档很少。

[DllImport("kernel32.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CancelIoEx(IntPtr hFile);

private void CancelReceive() {
   bool result = CancelIoEx(saeaCommunicationObject.AcceptSocket.Handle)
   // etc.
}

我得到result = false。我还尝试了CancelIo(),当我得到result = true时,当我尝试调用SetBuffer()时会抛出相同的异常。

TL; DR

一旦ReceiveAsync()被调用,所以现在套接字正在等待输入以触发Completed事件,如何取消此请求?

2 个答案:

答案 0 :(得分:1)

来自MSDN:

  

如果I / O操作处于挂起状态,则返回true。操作完成后,将引发e参数上的SocketAsyncEventArgs.Completed事件。   如果I / O操作同步完成,则返回false。在这种情况下,e参数上的SocketAsyncEventArgs.Completed事件不会被引发,并且在方法调用返回后立即检查作为参数传递的e对象以检索操作的结果。

因此,您应该检查ReceiveAsync电话的返回值。如果其true订阅SocketAsyncEventArgs.Completed事件。如果错误,请立即检查SocketAsyncEventArgs以验证结果。

答案 1 :(得分:0)

不是特定问题的答案,但我目前的解决方法是检查AcceptSocket.BytesAvailable值并等待它为>在致电ReceiveAsync()之前0。这样,如果我需要先调用SendAsync(),它就会被中断。

我认为这样效率会有所降低,而且我不确定它会有多大的可扩展性,考虑到可能有多达50个客户端同时连接 - 但它似乎让我超过这个驼峰现在。