C# 导致GC扫描并停止接收的连续UDP通信

C# 导致GC扫描并停止接收的连续UDP通信,c#,xamarin.android,android-asynctask,udp,threadpool,C#,Xamarin.android,Android Asynctask,Udp,Threadpool,我正在尝试从android设备与嵌入式UDP服务器通信,收到UDP数据包后,我正在更新我的UI。通信可以正常工作约250次迭代(查询-响应),然后弹出一个GC扫描主窗口,UDP套接字停止接收。我是android开发的新手,我不确定我的UDP通信的实现是否正确 这就是我所拥有的 void Initialize_UDP() { ThreadPool.QueueUserWorkItem(o => UDPCommunicator()); update

我正在尝试从android设备与嵌入式UDP服务器通信,收到UDP数据包后,我正在更新我的UI。通信可以正常工作约250次迭代(查询-响应),然后弹出一个GC扫描主窗口,UDP套接字停止接收。我是android开发的新手,我不确定我的UDP通信的实现是否正确

这就是我所拥有的

    void Initialize_UDP()
    {
        ThreadPool.QueueUserWorkItem(o => UDPCommunicator());
        update_flag = true;
    }

    void UDPCommunicator()
    {
        while (true)
        {
            if (update_flag)
            {
                try
                {
                    byte[] buffer = FrameGenerator(1, 0, true);
                    byte[] data = new byte[25];
                    CheckQuery(buffer);
                    var sender = default(IPEndPoint);
                    using (UdpClient udpClient = new UdpClient(15001))
                    {
                        udpClient.EnableBroadcast = true;
                        udpClient.Send(buffer, buffer.Length, "192.168.4.255", 15000);
                        udpClient.Client.ReceiveTimeout = 500;
                        data = udpClient.Receive(ref sender);
                        socket_active = false;
                    }
                    CheckResponse(data);
                    /*RunOnUiThread(() =>
                    {
                        Update_UI(data);
                    }); */
                }
                catch (SocketException)
                {
                    Log.Debug("Error", "Socket Error: Timeout");
                }
            }                
            Thread.Sleep(100);
        }
    }
这是我收到的错误

电话:35681185623120223800021149185

09-2514:20:01.896承兑交单(7595):查询:358110139

09-25 14:20:01.941 I/zygote(7595):显式并发复制GC释放4890(372KB)AllocSpace对象,0(0B)LOS对象,50%空闲,1628KB/3MB,暂停170us总计35.511ms

09-25 14:20:01.941 D/Mono(7595):GC_TAR_桥接21对象24不透明1颜色21颜色桥接21颜色可见21外部参照0缓存命中0缓存半命中0缓存未命中0设置0.07ms tarjan 0.06ms scc设置0.06ms聚集外部参照0.00ms外部参照设置0.00ms清理0.05ms

09-25 14:20:01.942 D/Mono(7595):GC_桥接器:完成,运行37.27毫秒

09-25 14:20:01.942 D/Mono(7595):GC_小调:(同时启动)时间5.32毫秒,stw 8.02毫秒提升114K大调尺寸:848K使用中:170K服务水平尺寸:17408K使用中:16067K

09-25 14:20:01.942 D/Mono(7595):地面指挥系统(主要)同时启动:(服务水平溢出)

09-25 14:20:02.442 D/错误(7595):套接字错误:超时
09-25 14:20:02.544 D/A(7595):查询:35 81 10 139这是超时时间太短的情况。
UdpClient.Client.ReceiveTimeout
是以毫秒为单位的时间。Stacktrace显示,“GC\u主\u并发\u启动:(LOS溢出)”和“套接字错误:超时”之间的时间正好为500毫秒,因此这就是原因。解决方法是增加UDP客户端的超时,默认值为“0”,表示无限,和/或向超时事件添加错误处理,正如BugFinder&MindSwipe指出的那样,创建一个新的UdpClient every循环会给GC带来不必要的负载,更好的替代方法是重用解决了问题的UdpClient。此外,以异步方式使用UDP池还可以进一步提高性能。下面是我的实现(为简洁起见简化)

void初始化_UDP()
{
UdpClient UdpClient=新的UdpClient();
UdpClient r_UdpClient=新的UdpClient(15001);
IPEndPoint发送方=默认值(IPEndPoint);
ManualResetEventSlim接收=新的ManualResetEventSlim(真);
运行(()=>UDP_传输());
}
异步无效UDP_传输()
{
字节[]帧;
SelectFrameQueue(选择器);
UDP客户=新的UDP客户(15001);
udpClient.EnableBroadcast=true;
udpClient.BeginReceive(新的异步回调(UDP_接收),udpClient);
while(true)
{
对于(int i=0;i
{
ShowToast(“连接超时。请检查设备”);
});
};
等待任务。延迟(更新延迟);//从H/W释放压力
receive.Reset();
}                             
}
}
无效UDP_接收(IAsyncResult结果)
{
receive.Set();
r_UdpClient=result.AsyncState作为UdpClient;
data=r_UdpClient.EndReceive(结果,参考发送方);
RunOnUiThread(()=>
{               
更新用户界面(数据);
});
r_UdpClient.BeginReceive(新的异步回调(UDP_接收),r_UdpClient);
}

您正在将UdpClient上的超时设置为500毫秒。GC在收集时冻结所有代码,看起来GC清理时间超过500 ms,或者添加了GC延迟,消息往返时间超过500 ms。只需将超时设置为更合理的时间,例如几秒钟,您是如何处理数据包丢失的?@BilalKazi不一定根据您展示的代码,您每次都会创建一个新的updclient,不要重复使用。。然后gcI不太同意BugFinder,创建一个新的UdpClient每个循环都会给GC带来不必要的负载。我建议您创建一次UdpClient,并在每次创建UdpClient时重用itnope,最终会有足够的内存混乱导致gc。通过拥有一个池,您可以处理多次,但保持内存使用,sameI将超时时间增加到5000毫秒,但这没有帮助。响应通常在200毫秒内从服务器收到,因此我认为“接收超时”不是原因。问题可能是来自服务器的UDP数据包没有到达。UDP不能保证数据包的可靠甚至有序传递(更多)。
void Initialize_UDP()
    {
        UdpClient udpClient = new UdpClient();
        UdpClient r_UdpClient = new UdpClient(15001);
        IPEndPoint sender = default(IPEndPoint);
        ManualResetEventSlim receive = new ManualResetEventSlim(true);
        Task.Run(() => UDP_Transmit());
    }

async void UDP_Transmit()
        {
            byte[] frame;
            SelectFrameQueue(selector);
            udpClient = new UdpClient(15001);
            udpClient.EnableBroadcast = true;
            udpClient.BeginReceive(new AsyncCallback(UDP_Receive), udpClient);
            while (true)
            {
                for (int i = 0; i < frame_Queue.Length; i++)
                {                    
                        frame = FrameGenerator(frame_Queue[i]);  //Generates Frames
                        try
                        {
                            udpClient.Send(frame, frame.Length, "192.168.4.255", 15000);
                        }
                        catch (SocketException)
                        {
                            Log.Debug("Error", "Socket Exception");
                        }

                        if(!receive.Wait(10000))   //Receive Timeout
                        {
                            RunOnUiThread(() =>
                            {
                                ShowToast("Connection Timeout. Please check device");
                            });
                        };
                        await Task.Delay(update_delay);    //To release pressure from H/W
                        receive.Reset();                        
                }                             
            }
        }

void UDP_Receive(IAsyncResult result)
        {
            receive.Set();
            r_UdpClient = result.AsyncState as UdpClient;
            data = r_UdpClient.EndReceive(result, ref sender);
            RunOnUiThread(() =>
            {               
                Update_UI(data);                            
            });
            r_UdpClient.BeginReceive(new AsyncCallback(UDP_Receive), r_UdpClient);            
        }