Using .NET 6.0.
I called BeginAccept like so:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
and my AcceptCallback method gets called as expected. I then have to call EndAccept to obtain the receive socket:
private static void AcceptCallback(IAsyncResult result)
{
Socket? listenSocket = result.AsyncState as Socket;
if (listenSocket == null)
{
// note: This is impossible but it helps getting the possible
// null reference warnings out of the way.
throw new ArgumentNullException(nameof(result.AsyncState), "The state object is null.");
}
Socket receiveSocket = listenSocket.EndAccept(
out byte[] buffer,
out int bytesRead,
result); // and here it blows up
The last call gives me a "System.ArgumentException: 'Value does not fall within the expected range. (Parameter 'asyncResult')'".
Apparently is has a problem with the last argument. It is not something I provide though, it is the result argument I get passed by the system which (according to the debugger) is a proper System.Threading.Tasks.TaskToApm.TaskAsyncResult. I am just following the examples I found.
I started out without the wrapping new AsyncCallback() in the call to BeginAccept because I did not understand what good it does (I would like to know though). I also initially had non-static methods. Because I had this problem I changed it to be more like the original examples but the same exception remains.
What is the problem and what can I do to overcome it?
[Edit]
As pointed out by Hans Passant the result argument should not be a System.Threading.Tasks.TaskToApm.TaskAsyncResult and this causes the error. There is little talk or documentation about TaskAsyncResult on the internet which made me suspicious, thinking it could be a bug in new framework code. So I rebuild with .NET 5.0 but the result was the same.
I am just using System.Net.Sockets.Socket classes, nothing fancy from a custom library or anything like that.
CodePudding user response:
It appears this first bit:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
makes it fail. If I change it to:
int maxSize = 0x2000; // 8K
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(maxSize, callback, state);
it succeeds, no exception anymore on EndAccept and I get the expected data in my ReceiveCallback (the next step in the asynchronous flow).
Because I was new to socket programming I figured it would be wise to start simple so I used the BeginAccept overload with the least parameters. I assumed it would use a default for maximum size. Well, whatever that "simple" overload does, it is not good.
So the type System.Threading.Tasks.TaskToApm.TaskAsyncResult for the result argument of AcceptCallback is perfectly fine, no problem there (I checked, it is still the same).
I can proceed now.
