Reputation: 56477
I'm working with dotnet core 2.2 and have the following UDP listener:
var socket = new Socket(ep.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
while (true)
{
var result = await socket.ReceiveFromAsync(...);
}
Now in certain scenarios I would like to interrupt the ReceiveFromAsync()
call. But it seems that unlike TCP case (i.e. ReceiveAsync()
) there is no ReceiveFromAsync()
overload accepting CancellationToken
.
One option would be to use Task.Delay(-1, ct);
together with Task.WhenAny()/Task.WhenAll()
. But I think that this solution leads to memory leak, right? I mean the .ReceiveFromAsync()
call still "exists" if interrupted, just in background. Also may lead to broken logic because such call will read an UDP packet and discard it afterwards? Or is my reasoning incorrect?
Another idea would be to have a background worker that reads from the UDP socket and queues each packet. And no interruption can happen here. Then I would read from the queue and interrupt this call. That would work but definitely requires some effort. The issues I see is: thread safety and performance.
Is there a cleaner/simplier way to handle this situation?
Upvotes: 1
Views: 622
Reputation: 456557
For "uncancelable" I/O requests, the standard pattern in Windows is to close the underlying handle - in this case, the socket. This generally causes any asynchronous (or synchronous, for that matter) operations to complete with an error code.
In your situation - "pausing" a UDP receiver - I think this approach especially makes sense. UDP sockets do not represent open connections anyway, so closing the socket is the best solution.
Regarding Task.Delay
with Task.WhenAny
, your concerns are perfectly valid. The Task.Delay
+ Task.WhenAny
approach only cancels the wait of the operation, not the operation itself. Specifically, it would not cancel the UDP receive, and that uncanceled UDP receive operation may get a packet that would then be "lost", since your app would ignore it.
Upvotes: 1