public static void RemoveAction(this UdpClient client, Delegate action)
        {
            try
            {
                var key = client.GetHashCode();

                if (udp_received_actions.ContainsKey(key))
                {
                    var temp = Delegate.RemoveAll(udp_received_actions[key], action);
                    udp_received_actions[key] = temp;
                }
            }
            catch { }
        }
        public static void ClearActions(this UdpClient client)
        {
            try
            {
                var key = client.GetHashCode();
                if (udp_received_actions.TryRemove(key, out Delegate a))
                {
                    a = null;
                }

                if (task_tokens.TryRemove(key, out CancellationTokenSource t))
                {
                    t.Cancel();
                    t.Dispose();
                }
            }
            catch { }
        }
        public static void WhenReceived(this UdpClient client, Action <UdpReceiveResult> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException();
            }
            var key = client.GetHashCode();

            if (udp_received_actions.ContainsKey(key))
            {
                var temp = Delegate.Combine(udp_received_actions[key], action);
                udp_received_actions[key] = temp;
            }
            else
            {
                udp_received_actions[key] = action;
            }

            if (task_tokens.ContainsKey(key))
            {
                return;
            }
            var cts     = new CancellationTokenSource();
            var context = SynchronizationContext.Current;

            Task.Run(async() =>
            {
                while (true)
                {
                    try
                    {
                        if (cts.IsCancellationRequested)
                        {
                            break;
                        }
                        var r = await client.ReceiveAsync();
                        if (udp_received_actions.ContainsKey(key))
                        {
                            var a = udp_received_actions[key];
                            if (context == null)
                            {
                                a.DynamicInvoke(r);
                            }
                            else
                            {
                                context.Post(_ =>
                                {
                                    a.DynamicInvoke(r);
                                }, null);
                            }
                        }
                    }
                    catch
                    {
                        if (task_tokens.TryRemove(key, out cts))
                        {
                            cts.Dispose();
                        }
                        break;
                    }
                }
            }, cts.Token).ConfigureAwait(false);
            task_tokens[key] = cts;
        }