2

I have the following method listening to UDP broadcasts:

    private async Task ReciveBroadCast()
    {
        var recv = await udpReceiver.ReceiveAsync(); 
        var remoteEndPoint = recv.RemoteEndPoint;
        string message = Encoding.ASCII.GetString(recv.Buffer); //TODO: Do something with this message
        var answer = "ok";
        var answerBuffer = Encoding.UTF8.GetBytes(answer);
        udpReceiver.Send(answerBuffer, 2, remoteEndPoint);
    }

Listening to the broadcasts gets started by the user pressing a button. I would also like to be able to stop listening, however there seems to be no way of cancelling the ReceiveAsync() method.

The only answer I could find so far is from this post: How to to make UdpClient.ReceiveAsync() cancelable?

I was wondering if I missed a better way to do this (since the linked post is quite a few years old)? Or maybe there is a way to generally cancel async methods immediately if a Cancellation Token can't be checked periodically?

Roland Deschain
  • 2,211
  • 19
  • 50
  • Perhaps the "why" question should be sent to Microsoft using an issue on their [github repo](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs) – Lasse V. Karlsen Mar 23 '21 at 11:58
  • @LasseV.Karlsen "why" question? Do you mean in terms of "why is there no timeout/CancellationToken build into this method"? – Roland Deschain Mar 23 '21 at 12:02
  • 1
    As long as the `Socket` class itself does not support cancellable receives, `UdpClient` isn't going to get it either. For `Socket` it's [being worked on](https://github.com/dotnet/runtime/issues/43935). Once that's done it would be trivial to extend `UdpClient` (although it's not fomally part of the work list yet, unlike `TcpClient`). – Jeroen Mostert Mar 23 '21 at 12:04
  • @JeroenMostert ok, so for now the linked answer in my post is then probably the way to go, right? – Roland Deschain Mar 23 '21 at 12:06
  • 2
    I would argue that picking up the work and submitting a pull request is the very *best* way to go, but assuming you don't want to put in that work *and* wait for .NET 6 to land, any alternative that adds cancellation to a non-cancellable task with a custom timeout will do. Do note the comments on that answer: this is OK if you're pretty much "done" after cancelling, but not OK if you want to do this repeatedly without closing the socket, as the original operation itself is (of course) never truly cancelled. Aside from tying up resources, you can also miss packets this way. – Jeroen Mostert Mar 23 '21 at 12:10

1 Answers1

0

This feature has been added in .NET 6:

https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.udpclient.receiveasync?view=net-6.0#system-net-sockets-udpclient-receiveasync(system-threading-cancellationtoken)

I recently ran into this exact problem on a .Net Core 3.1 project; no good way around it other than through accessing the socket directly (UdpClient.Client), but it's nice to have it available in. NET 6, as many projects can (and will) be upgraded.

Here is the relevant discussion on GitHub, in case you can't upgrade yet:

https://github.com/dotnet/runtime/issues/921#issuecomment-498299946

CoolBots
  • 4,770
  • 2
  • 16
  • 30