Winforms WinForm应用程序停止运行并冻结windows
我不熟悉Windows开发。 我开发了一个WinForm应用程序,它可以与串行设备通信并在图表上绘制数据。 应用程序应每天7/7天24小时运行。代码执行正确,但在执行数小时后,UI冻结在无响应操作系统上(我必须关闭电脑并重新启动) 串行类(使用Winforms WinForm应用程序停止运行并冻结windows,winforms,Winforms,我不熟悉Windows开发。 我开发了一个WinForm应用程序,它可以与串行设备通信并在图表上绘制数据。 应用程序应每天7/7天24小时运行。代码执行正确,但在执行数小时后,UI冻结在无响应操作系统上(我必须关闭电脑并重新启动) 串行类(使用System.IO.port)在单独的线程上执行读写操作。 这个场景让我想到了从串行类到UI的一个不正确的跨线程调用。阅读微软的文档和其他问题,我想我已经修复了错误,但没有办法,应用程序继续冻结操作系统 写操作通过串行方式每100ms向主板发送一个请求字符
System.IO.port
)在单独的线程上执行读写操作。
这个场景让我想到了从串行类到UI的一个不正确的跨线程调用。阅读微软的文档和其他问题,我想我已经修复了错误,但没有办法,应用程序继续冻结操作系统
写操作通过串行方式每100ms向主板发送一个请求字符,我使用System.Threading.Timer这样做,因为此操作不会与UI交互
//Initialization
WriteTimer = new Timer(Write, COMport.IsOpen, 5000, 100);
// callback function
public static void Write(object state)
{
if ((bool) state)
{
try
{
COMport.Write("^");
}
catch (Exception exc)
{
ErrorLogger.WriteTxtLog(DateTime.Now,exc.ToString());
}
}
}
串行板以10字节的字符串回复请求字符,以读取消息,我正在使用DataReceived
事件处理程序表单IO.port
,它也在一个单独的线程上执行,接收到的数据将被详细说明,然后通过一个事件处理程序委托传递给UI,该委托在主窗体类上声明了args。我将表单控件传递给serial类以进行安全线程调用
// FormControl is passed in the constructor of the serial class:
public Form1 FormControl;
private void COMport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort port = (SerialPort) sender;
byte[] buffer = new byte[10];
try
{
for (int i = 0; i < buffer.Length && buffer[i]!=3 ; i++)
{
buffer[i] = (byte) port.ReadByte();
}
SerialDataArgs args = checkDataReceived(buffer);
if (!args.error)
{
FormControl.Invoke(FormControl.drItem, new SerialDataArgs(...));
}
else
{
FormControl.Invoke(FormControl.drItem, new SerialDataArgs(0,0,true));
ErrorLogger.WriteTxtLog(DateTime.Now, "");
}
}
catch (Exception exc)
{
ErrorLogger.WriteTxtLog(DateTime.Now, exc.ToString());
}
}
也许错误不在这里,但在我看来,在窗口崩溃之前,这似乎是唯一感兴趣的部分。对不起,我的英语不好,希望我提出了一个正确/不重复的问题。使用Control.BeginInvoke
而不是Control.Invoke
根据我的经验,System.IO.Ports.SerialPort
的问题通常只会导致UI冻结,而不会导致操作系统冻结,当试图使用控件从SerialPort.DataReceived
事件更新UI时出现死锁。调用
,UI线程本身尝试访问SerialPort
对象,例如关闭它。在这种情况下,当UI线程等待SerialPort
DataReceived
线程完成,而DataReceived
线程等待UI线程完成控件时,可能会出现死锁。调用。为了克服这类问题,最好使用Control.BeginInvoke
,这样DataReceived
线程就不会等待UI线程
使用lock
同步对共享资源的访问
从不同线程访问同一对象时,用于同步数据访问。无同步数据访问可能会导致所有不同的问题
检查串行端口驱动程序或连接是否有问题
当UI冻结且操作系统无响应时,请尝试移除串行端口设备,并查看操作系统是否响应。如果是这样,问题可能不在应用程序中,而在串行端口驱动程序或连接中
希望这有帮助谢谢,我更正了代码并找出了问题所在。它不是在串行通信上,也不是无效的跨线程操作,而是在另一个FTDI设备或驱动程序上。
SerialClass Serial = null;
public delegate void DataReceived(SerialDataArgs args);
public DataReceived drItem;
void ConnectCOM()
{
// COM READ
if (Serial == null)
{
Serial = new SerialClass(param.comName, this //this should be the FORM CONTROL);
if (Serial.Open)
{
...
drItem += HandleSeriaData;
}
else
{
...
}
}
}
//EventHandler
private void HandleSeriaData(SerialDataArgs args)
{
if (!args.error)
{
Work(args...); // in the work method i'll update labels, drawGraph,....
}
else
{
if (!Serial.Open) RecoverySerial();
}
}