diff --git a/csharp/Platform.Protocols/Udp/UdpReceiver.cs b/csharp/Platform.Protocols/Udp/UdpReceiver.cs index 265c2c4..dedef33 100644 --- a/csharp/Platform.Protocols/Udp/UdpReceiver.cs +++ b/csharp/Platform.Protocols/Udp/UdpReceiver.cs @@ -1,7 +1,9 @@ using System; +using System.Linq; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Threading; +using System.Threading.Tasks; using Platform.Disposables; using Platform.Exceptions; using Platform.Threading; @@ -26,7 +28,8 @@ public class UdpReceiver : DisposableBase //-V3073 { private const int DefaultPort = 15000; private bool _receiverRunning; - private Thread _thread; + private Task? _receiverTask; + private CancellationTokenSource _cancellationTokenSource; private readonly UdpClient _udp; private readonly MessageHandlerCallback _messageHandler; @@ -65,6 +68,7 @@ public UdpReceiver(int listenPort, bool autoStart, MessageHandlerCallback messag { _udp = new UdpClient(listenPort); _messageHandler = messageHandler; + _cancellationTokenSource = new CancellationTokenSource(); if (autoStart) { Start(); @@ -119,11 +123,10 @@ public UdpReceiver() : this(DefaultPort, true, message => { }) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Start() { - if (!_receiverRunning && _thread == null) + if (!_receiverRunning && _receiverTask == null) { _receiverRunning = true; - _thread = new Thread(Receiver); - _thread.Start(); + _receiverTask = Task.Run(() => Receiver(_cancellationTokenSource.Token)); } } @@ -136,11 +139,19 @@ public void Start() [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Stop() { - if (_receiverRunning && _thread != null) + if (_receiverRunning && _receiverTask != null) { _receiverRunning = false; - _thread.Join(); - _thread = null; + _cancellationTokenSource.Cancel(); + try + { + _receiverTask.Wait(); + } + catch (AggregateException ex) when (ex.InnerExceptions.All(e => e is OperationCanceledException)) + { + // Expected when cancellation is requested + } + _receiverTask = null; } } @@ -166,9 +177,9 @@ public void Stop() [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ReceiveAndHandle() => _messageHandler(Receive()); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Receiver() + private void Receiver(CancellationToken cancellationToken) { - while (_receiverRunning) + while (_receiverRunning && !cancellationToken.IsCancellationRequested) { try { @@ -208,6 +219,7 @@ protected override void Dispose(bool manual, bool wasDisposed) if (!wasDisposed) { Stop(); + _cancellationTokenSource?.Dispose(); _udp.DisposeIfPossible(); } }