我正在为我的大学学位创建一个远程管理工具。我目前确实陷入了我代码中的一个错误,想知道是否有人可以阐明我的问题。
我有应用程序、服务器和客户端。服务器运行良好。然而,客户端是卡住的应用程序。
在连接到服务器之前,客户端运行良好。当连接到服务器时,客户端会一直卡住在屏幕上。
我已将错误缩小到特定代码段,没有这段代码运行应用程序不会卡住。但是,该应用程序也不起作用。
这是该代码的示例:
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
很好,这是诊断问题的第一步。 走得更远。这里究竟有哪些方法具有高延迟?我的猜测是 Receive
或 Read
,但有几个可能的候选者,而且可能不止一个。
一旦您确定了每个高延迟方法,确定它速度慢是因为它正在使用 CPU 还是因为等待 IO。
如果它因为使用 CPU 而变慢,您要做的是将该操作移至另一个 CPU 并等待结果。您可以按照其他答案的建议这样做:使用 Task.Run
将工作移至后台线程,然后 await
结果。
如果它因为等待 IO 而变慢,那么不要将操作移至后台线程,除非您别无选择。后台工作 API 旨在将工作卸载到其他 CPU,而 IO 不是 CPU 绑定(bind)的工作。您在这里要做的是使用异步 IO 操作。例如,如果阻止程序是 Receive
,则使用 ReceiveAsync
并 await
结果 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/