c# - 如何阻止我的 UI 卡住?

标签 c# winforms user-interface

我正在为我的大学学位创建一个远程管理工具。我目前确实陷入了我代码中的一个错误,想知道是否有人可以阐明我的问题。

我有应用程序、服务器和客户端。服务器运行良好。然而,客户端是卡住的应用程序。

在连接到服务器之前,客户端运行良好。当连接到服务器时,客户端会一直卡住在屏幕上。

我已将错误缩小到特定代码段,没有这段代码运行应用程序不会卡住。但是,该应用程序也不起作用。

这是该代码的示例:

private static void ReceiveResponse()
    {

        var buffer = new byte[2048]; //The receive buffer

        try
        {
            int received = 0;
            if (!IsLinuxServer) received = _clientSocket.Receive(buffer, SocketFlags.None); //Receive data from the server
            else received = _sslClient.Read(buffer, 0, 2048);
            if (received == 0) return; //If failed to received data return
            var data = new byte[received]; //Create a new buffer with the exact data size
            Array.Copy(buffer, data, received); //Copy from the receive to the exact size buffer

            if (isFileDownload) //File download is in progress
            {
                Buffer.BlockCopy(data, 0, recvFile, writeSize, data.Length); //Copy the file data to memory

                writeSize += data.Length; //Increment the received file size

                if (writeSize == fup_size) //prev. recvFile.Length == fup_size
                {


                    using (FileStream fs = File.Create(fup_location))
                    {
                        Byte[] info = recvFile;
                        // Add some information to the file.
                        fs.Write(info, 0, info.Length);
                    }

                    Array.Clear(recvFile, 0, recvFile.Length);
                    SendCommand("frecv");
                    writeSize = 0;
                    isFileDownload = false;
                    return;
                }
            }

            if (!isFileDownload) //Not downloading files
            {
                string text = (!IsLinuxServer) ? Encoding.Unicode.GetString(data) : Encoding.UTF8.GetString(data); //Convert the data to unicode string
                string[] commands = GetCommands(text); //Get command of the message



                foreach (string cmd in commands) //Loop through the commands
                {
                    HandleCommand(Decrypt(cmd)); //Decrypt and execute the command
                }
            }
        }
        catch (Exception ex) //Somethind went wrong
        {
            MessageBox.Show(ex.Message);
            RDesktop.isShutdown = true; //Stop streaming remote desktop
           // MessageBox.Show("Connection ended");
        }
    }

这段代码是用户如何接收来自服务器的请求。所以它在一个定时器中每 100 毫秒运行一次。

我想知道计时器是否与此有关。在它处于 While(true) 循环之前,我遇到了同样的问题,这让我认为这是使 UI 卡住的实际代码。

即使应用程序被卡住,代码仍然可以工作,应用程序上的所有内容都可以工作,除了 UI。

这真的很令人沮丧,我真的看不出任何会导致应用程序卡住的代码错误。

任何帮助将不胜感激。

提前谢谢你。

最佳答案

到目前为止有六个答案,没有任何有用、正确或可操作的建议。忽略它们。

I've narrowed the bug down to a specific piece of code, without this code running the application doesn't freeze

很好,这是诊断问题的第一步。 走得更远。这里究竟有哪些方法具有高延迟?我的猜测是 ReceiveRead,但有几个可能的候选者,而且可能不止一个。

一旦您确定了每个高延迟方法,确定它速度慢是因为它正在使用 CPU 还是因为等待 IO。

如果它因为使用 CPU 而变慢,您要做的是将该操作移至另一个 CPU 并等待结果。您可以按照其他答案的建议这样做:使用 Task.Run 将工作移至后台线程,然后 await 结果。

如果它因为等待 IO 而变慢,那么不要将操作移至后台线程,除非您别无选择。后台工作 API 旨在将工作卸载到其他 CPU,而 IO 不是 CPU 绑定(bind)的工作。您在这里要做的是使用异步 IO 操作。例如,如果阻止程序是 Receive,则使用 ReceiveAsyncawait 结果 Task

您还应该使您的方法async 并返回一个Task 然后由其调用者等待,依此类推直到事件处理程序启动整个过程.

继续执行此过程,直到您识别出方法中每个耗时超过 30 毫秒的操作,并使其在工作线程上异步(如果受 CPU 限制)或使用异步 IO 方法(如果受 IO 限制)。您的 UI 不应有超过 30 毫秒的延迟。

谈到事件处理程序...

This code is how the user receives a request from the server. So it is in a timer to be run every 100ms.

这听起来非常非常错误。首先,“收到来自服务器的请求”?服务器代表客户端发出请求,反之亦然。

其次,这听起来像是一种错误的处理问题的方法。

如果你正确地异步化这段代码,就不需要定时器来不断地轮询套接字。您应该简单地异步读取,并且读取成功并回调您,或者超时。

另外,这里没有循环。你说你每 100 毫秒运行一次这段代码,你在这里最多读取 2K,所以无论你的网络连接有多饱和,你每秒最多读取 20K,对吧?你觉得这样对吗?因为这对我来说似乎是错误的。

关于c# - 如何阻止我的 UI 卡住?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49859237/

相关文章:

winforms - 将 Form.ShowDialog() 代码重构为 MVP

c# - 从视频文件中提取wav文件

Java swing简单通讯录事件错误

.net - 为什么在关闭带有 WebBrowser 控件的窗体时出现 RaceOnRCWCleanup 错误?

android - 在 Android 应用程序中实现设计的最佳方式?

c# - 有限状态机与另一种在 C# 中进行 UI 测试的技术

C# 流水线函数数组签名

c# - 无法在不崩溃的情况下从 ComboBox 中删除项目

c# - 如何避免两个 Controller 操作之间出现 AmbiguousMatchException?

c# - Breeze 导航属性未加载