Reputation: 3646
I am receiving this error sometimes:
An asynchronous socket operation is already in progress using this SocketAsyncEventArgs instance.
...when I try to call SocketServiceEventArgs.SetBuffer()
I realise this is because an instance can only perform one operation and it must be in use. However I am calling it again because after a previous timeout from the client side, I wish to attempt to resend the request. I don't wish to close this socket and use a new one because then the connection will be broken with the client.
However, what I need to do is check whether another operation is already in progress before doing this, and if so, terminate it, so that I can send again.
The code I am using to send is
saeaCommunicationObject.AcceptSocket.SendAsync(saeaCommunicationObject)
but what's more likely to be in progress is the Receive which is
saeaCommunicationObject.AcceptSocket.ReceiveAsync(saeaCommunicationObject))
(saeaCommunicationObject
is a SocketAsyncEventArgs
).
In research, I have come across
AcceptSocket.EndReceive(IAsyncResult asyncResult)
but I'm not sure if this is correct, and also I have no idea where to get asyncResult (so if this is correct, my question is, where is this supposed to come from?)
So what can I do to either check if it's in progress (and if so, terminate it)?
Edit
One place I looked suggested (but did not recommend) the use of CancelIoEx()
using P/Invoke - however I couldn't get this to work and there is very little documentation on this.
[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.
}
I get result
= false
. I've also tried CancelIo()
and while I get result
= true
, the same exception is thrown when I try to call the SetBuffer()
.
TL;DR
Once ReceiveAsync()
is called and so now the socket is waiting on input in order to fire the Completed
event, how do I cancel this request?
Upvotes: 4
Views: 4328
Reputation: 3646
Not quite an answer to the specific question, but my current workaround is to check the AcceptSocket.BytesAvailable
value and wait for it to be > 0 before calling ReceiveAsync()
. That way it can be interrupted if I need to call SendAsync()
first.
I think that this will be a little less efficient and I'm not sure how scaleable it will be, considering there could be up to 50 clients connecting at the same time - but it seems to be getting me over this hump for now.
Upvotes: 1
Reputation: 1086
From MSDN:
Returns true if the I/O operation is pending. The SocketAsyncEventArgs.Completed event on the e parameter will be raised upon completion of the operation. Returns false if the I/O operation completed synchronously. In this case, The SocketAsyncEventArgs.Completed event on the e parameter will not be raised and the e object passed as a parameter may be examined immediately after the method call returns to retrieve the result of the operation.
So, you should check the return value of the ReceiveAsync
call. If its true
subscribe to the SocketAsyncEventArgs.Completed
event. If it's false then check the SocketAsyncEventArgs
immediately to verify the result.
Upvotes: 2