/// <summary></summary>
private Byte[] _ReceiveBytes(Int32 size)
{
MemoryStream memory = null;
SocketAsyncEventArgs args = null;
EventHandler<SocketAsyncEventArgs> completed = null;
Exception exception = null;
Int32 last_update = Environment.TickCount;
Boolean finished = false;
Int32 count = 0;
Int32 received = 0;
completed = new EventHandler<SocketAsyncEventArgs>((s, e) =>
{
try
{
count = e.BytesTransferred;
last_update = (count > 0 ? Environment.TickCount : last_update);
memory.Write(e.Buffer, 0, count);
received += count;
finished = (received == size);
if (!finished)
{
count = Math.Min(_ChunkSize, size - received);
args.SetBuffer(new Byte[count], 0, count);
if (!_Socket.ReceiveAsync(e))
{
completed(s, e);
}
}
}
catch (Exception ex)
{
exception = ex;
}
});
using (memory = new MemoryStream())
using (args = new SocketAsyncEventArgs())
{
count = Math.Min(_ChunkSize, size - received);
args.SetBuffer(new Byte[count], 0, count);
args.Completed += completed;
if (!_Socket.ReceiveAsync(args))
{
completed(_Socket, args);
}
while (!finished)
{
Thread.Sleep(_SleepTimeSpan);
if (exception != null)
{
throw new Exception(_ReceiveExceptionMessage, exception);
}
else if (!finished && Environment.TickCount - last_update > _ReceiveTimeout)
{
throw new TimeoutException(_TimeoutExceptionMessage);
}
}
return memory.ToArray();
}
}
views:
116answers:
1
+2
A:
There are problems. "finished" needs to be volatile but can't be, use MRE. Your timeout code can crash on a OverflowException. You're translating exceptions.
But the approach makes no sense, there's no point in waiting for an async operation to complete. Use Socket.ReceiveTimeout to get the timeout exception.
Hans Passant
2009-12-03 03:17:02
I don't think finished needs to be volatile in this case. http://stackoverflow.com/questions/59422/is-a-bool-read-write-atomic-in-c
ChaosPandion
2009-12-09 02:08:07