Кто подписан на OnRecieved? using Newtonsoft.Json;
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TheRepresentationOfTheDateInPsycholophysiology.Services
{
    public class UdpSendReceiveService<TSend, TReceive> : IDisposable
    {
        public event Action<TReceive> OnReceived;

        private readonly UdpClient udpClient;
        private CancellationTokenSource cancellationTokenSource;

        private readonly JsonConverterService<TSend> jsonConverterSend;
        private readonly JsonConverterService<TReceive> jsonConverterReceive;

        private readonly IPAddress ipAddress;
        private readonly int sendPort;
        private readonly int receivePort;
        private bool isRunning = false;

        public TSend DataToSend { get; set; }

        public UdpSendReceiveService(IPAddress ipAddress, int sendPort, int receivePort)
        {
            this.ipAddress = ipAddress;
            this.sendPort = sendPort;
            this.receivePort = receivePort;

            this.udpClient = new UdpClient(receivePort);
            this.cancellationTokenSource = new CancellationTokenSource();

            this.jsonConverterSend = new JsonConverterService<TSend>();
            this.jsonConverterReceive = new JsonConverterService<TReceive>();

            //Task.Run(() => ReceiveLoopAsync());
        }

        public void Dispose() => Disconnect();

        private async Task ReceiveLoopAsync()
        {
            while (!cancellationTokenSource.Token.IsCancellationRequested)
            {
                try
                {
                    var data = await udpClient.ReceiveAsync();
                    string message = Encoding.UTF8.GetString(data.Buffer);

                    if (!string.IsNullOrEmpty(message))
                    {
                        var receivedObject = jsonConverterReceive.Deserialize(message);
                        OnReceived?.Invoke(receivedObject);
                    }
                }
                catch (JsonException ex)
                {
                    Console.WriteLine($"JSON parsing error: {ex.Message}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error receiving data: {ex.Message}");
                }
            }
            Disconnect();
        }

        private void Disconnect()
        {
            cancellationTokenSource?.Cancel();
            udpClient?.Close();
        }

        public void StartSending()
        {
            isRunning = true;
            Task.Run(() => SendLoop());
        }

        private async Task SendLoop()
        {
            using (var udpSender = new UdpClient())
            {
                IPEndPoint endPoint = new IPEndPoint(ipAddress, sendPort);

                while (isRunning)
                {
                    string message = jsonConverterSend.Serialize(DataToSend);
                    byte[] data = Encoding.UTF8.GetBytes(message);

                    await udpSender.SendAsync(data, data.Length, endPoint);
                    await Task.Delay(30);
                }
            }
        }

        public void StopSending()
        {
            isRunning = false;
        }
    }

    public class JsonConverterService<T>
    {
        public string Serialize(T obj)
        {
            return JsonConvert.SerializeObject(obj);
        }

        public T Deserialize(string json)
        {
            return JsonConvert.DeserializeObject<T>(json);
        }
    }
}