ajustes contra corrida
This commit is contained in:
parent
c03c5b1736
commit
e718a3858f
|
|
@ -21,6 +21,7 @@ using System.Diagnostics;
|
|||
using Newtonsoft.Json;
|
||||
using AgroMonitor;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace AgroBase.Models
|
||||
{
|
||||
|
|
@ -328,9 +329,24 @@ namespace AgroBase.Models
|
|||
double ms = (DateTime.UtcNow - lastPkt).TotalMilliseconds;
|
||||
|
||||
if (ms > UDP_RESTART_MS)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RestartUdpChannelSafe();
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
// normal durante restart
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// normal durante restart
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("[UDP] Watchdog exception: " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
private CancellationTokenSource _hbCts;
|
||||
private Task _hbTask;
|
||||
private int _hbRunning = 0;
|
||||
private readonly object _sockLock = new object();
|
||||
private volatile bool _stopping = false;
|
||||
|
||||
|
||||
public void SetRemote(string ip, int port)
|
||||
|
|
@ -71,37 +73,37 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
|
||||
public void Stop()
|
||||
{
|
||||
lock (_sockLock)
|
||||
{
|
||||
_stopping = true;
|
||||
_running = false;
|
||||
}
|
||||
|
||||
// pare heartbeat antes de matar socket
|
||||
StopHeartbeat();
|
||||
|
||||
try { _udp?.Close(); } catch { } // força o Receive quebrar
|
||||
try { _udp?.Dispose(); } catch { } // garante liberar socket
|
||||
try { _udp?.Close(); } catch { }
|
||||
try { _udp?.Dispose(); } catch { }
|
||||
|
||||
// espera thread encerrar (pra não ficar thread velha viva)
|
||||
try
|
||||
{
|
||||
if (_rxThread != null && _rxThread.IsAlive)
|
||||
{
|
||||
if (!_rxThread.Join(500))
|
||||
{
|
||||
// Se travar, não aborta (Thread.Abort é treta), só segue.
|
||||
// Mas normalmente Close() já libera.
|
||||
}
|
||||
}
|
||||
_rxThread.Join(500);
|
||||
}
|
||||
catch { }
|
||||
|
||||
lock (_sockLock)
|
||||
{
|
||||
_udp = null;
|
||||
_rxThread = null;
|
||||
|
||||
// reseta sequência RX pra evitar descartar tudo após restart
|
||||
_lastSeqRx = 0;
|
||||
|
||||
// opcional: limpa ACKs pendentes pra não vazar
|
||||
foreach (var kv in _pendingAck)
|
||||
kv.Value.TrySetResult(false);
|
||||
_pendingAck.Clear();
|
||||
|
||||
_stopping = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -214,8 +216,19 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
|
||||
private Task SendInternalAsync(byte type, byte[] payload, uint seq, uint tsMs, bool requestAck)
|
||||
{
|
||||
if (_udp == null) throw new InvalidOperationException("Channel not started.");
|
||||
if (Remote == null) throw new InvalidOperationException("Remote not set.");
|
||||
UdpClient udp;
|
||||
IPEndPoint remote;
|
||||
|
||||
lock (_sockLock)
|
||||
{
|
||||
if (_stopping || !_running) return Task.CompletedTask;
|
||||
|
||||
udp = _udp;
|
||||
remote = Remote;
|
||||
}
|
||||
|
||||
if (udp == null) return Task.CompletedTask;
|
||||
if (remote == null) return Task.CompletedTask;
|
||||
|
||||
if (payload.Length > MaxPayloadBytes)
|
||||
throw new ArgumentException("Payload too big (" + payload.Length + " > " + MaxPayloadBytes + ").");
|
||||
|
|
@ -223,7 +236,6 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
byte flags = (byte)(requestAck ? 1 : 0);
|
||||
|
||||
byte[] buf = new byte[12 + payload.Length];
|
||||
// magic BE
|
||||
buf[0] = (byte)(MAGIC >> 8);
|
||||
buf[1] = (byte)(MAGIC & 0xFF);
|
||||
buf[2] = type;
|
||||
|
|
@ -235,8 +247,18 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
if (payload.Length > 0)
|
||||
Buffer.BlockCopy(payload, 0, buf, 12, payload.Length);
|
||||
|
||||
// UdpClient.SendAsync existe no .NET Framework 4.6+, ok.
|
||||
return _udp.SendAsync(buf, buf.Length, Remote);
|
||||
try
|
||||
{
|
||||
return udp.SendAsync(buf, buf.Length, remote);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private void RxLoop()
|
||||
|
|
|
|||
Loading…
Reference in New Issue