views:

44

answers:

3

Hello all. I was using the following code to send data asynchronously but I noticed that using WaitOne in the AsyncWaitHandle that I get from asyncRes doesn't wait at all. I checked MSDN and it says I should use a ManualResetEvent.

...
var asyncRes = _socket.BeginSend(encodedFrame, 0, encodedFrame.Length, SocketFlags.None, sendCallback, _socket);
...
var success = asyncRes.AsyncWaitHandle.WaitOne(_timeout, true);
...


 private void sendCallback(IAsyncResult ar)
 {
     _socket.EndSend(ar);            
 }

MSDN also says in IAsyncResult:

AsyncWaitHandle: Gets a WaitHandle that is used to wait for an asynchronous operation to complete.

So why can't I use it for that purpose?

Thank you.

+1  A: 

Setting the 2nd param to true is saying you don't want to wait. Set the 2nd param to false and you should see the result you want.

By setting the 2nd param to true you are basically saying "abort".

Hogan
Doesn't work. WaitOne still ignores my timeout.
jassuncao
The call to waitone does not include a timeout. The first parameter is a returned value measuring the time waited. http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitone(v=VS.71).aspx
Hogan
+1  A: 

Because you are not supposed to?

The Begin/End async convention is meant to be used in pair, this example might be too simple to illustrate why you would want to do it like this, but the fact is that you don't need to do it like that, you can do this as well.

var ar = _socket.BeginSend(encodedFrame, 0, encodedFrame.Length, SocketFlags.None);
//...
_socket.EndSend(ar); // this is a blocking operation

I don't see the point in using async IO if you end up blocking anyway...

John Leidegren
The point is that he has some stuff he wants to do and then when he finishes with that he wants to wait. Makes sense to me.
Hogan
That's still possible with the above approach...
John Leidegren
+2  A: 

Not sure if I understand the problem correctly. But this is normal behavior. BeginSend means "do this asynchronously if you have to". It doesn't have to very often. In many cases, the send can be completed synchronously because there was enough space in the kernel memory pool to store the bytes. That only needs a very fast memory-to-memory copy and the overlapped I/O transfer completes immediately.

Another good example of this is FileStream.BeginWrite(), that writes to the file system cache. You typically have to write more than a gigabyte before that fills up the cache and starts taking time.

Anyhoo, under these circumstances the WaitOne() call will return immediately and not use the timeout. Raymond Chen just blogged about this recently. From a native API point of view but that's what is being used here. I don't think you've got a real problem here, just Windows working efficiently.

Hans Passant
I guess that is what is happening. I assumed WaitOne would only return successful after an endSend but I guess that might not be true. While trying to simulate a send timeout using a sleep before invoking endSend, I noticed the waitHandle was released before endSend was invoked.
jassuncao
Yes, that would happen if the transfer was completed synchronously. Use your own AutoResetEvent, call Set() in the callback.
Hans Passant