我有一个用于通过rs232与硬件通信的程序。该软件用于显示通过rs232从硬件推送到尽可能快的数据流。我遇到的问题是,随着时间的推移,分配给程序的私有内存会爆炸,并且会很快崩溃程序。如果我禁止硬件发送数据大约2分钟,那么软件可以清除内存,但仅限于暂停数据流。
我正在使用SerialPort中的DataReceived事件,这似乎是问题所在,因为即使DataReceived函数在其中没有任何内容,它也会导致内存峰值。我唯一能想到的是,每次引发此事件时,它都会创建一个新线程来运行,并且它发生的速度非常快,以至于计算机没有时间在数据进入时运行GC。
是否有更有效的方法从SerialPort对象中提取数据?收到“NewLine”时,我只关心字符串?
谢谢,
John Vickers
答案 0 :(得分:4)
DataReceived在不同的线程上执行。我遇到了非常快的数据问题,这个事件给我带来了问题。因此,我创建了一个线程并自己读取数据:
while (this.serialPort.IsOpen)
{
int b = this.serialPort.ReadByte();
if (b != -1)
{
// data is good here
}
}
但就像其他人所说的那样,没有任何代码示例,我们可以帮助您的不多。
答案 1 :(得分:4)
非常不寻常但技术上可行。 SerialPort使用线程池线程来调用DataReceived事件处理程序。一旦收到一个或多个字节,它就会抓取TP线程通知您的应用。事件生成代码中存在锁定,一次只能有一个线程调用您的事件处理程序。
这里潜在的失败模式是这些调用中的一个(可能是第一个)在您的代码中进入一个从不退出的循环。如果您尚未设置Handshake属性,则设备可以继续发送并触发更多TP呼叫,所有这些都会阻止该锁定。
从Debug + Windows + Threads窗口进行诊断。如果我的猜测是准确的,那么你应该看到这里列出了大量的线程。其中一个应该在DataReceived事件处理程序中,双击它并查看调用堆栈以查看它被卡住的位置。您看到的内存被这些线程的堆栈吃掉,每个线程一个兆字节。
另一种可能性是,您的DataReceived事件处理代码非常慢,可能是通过调用Control.Invoke()。足够慢,无法跟上设备。您现在确实需要使用Handshake属性来设置流控制。或修复任何使它如此缓慢的东西。还应该有非常多的ErrorReceived事件,一定要实现它,这样你就可以看到这个东西出错了。
可以同时运行的TP线程数有一个上限。它相当慷慨,是核心数量的250倍。在典型的双核机器上,这很容易消耗半千兆字节的内存。
答案 2 :(得分:0)
只是为了重振这个问题。
使用DataReceived事件时,我发现存在大量内存泄漏。
我正在使用提供串行调制解调器接口的USB 3G调制解调器。我写了一个小程序,只打开串口并连接到DataReceived事件。事件处理程序只是一个空方法。
如果你猛拉了加密狗,内存开始以每秒10MB的速度泄漏。没有例外。
启动一个新线程并使用同步Read(...)方法为我解决了这个问题。当我拿出我能处理的加密狗并且没有内存泄漏时,我现在得到一个例外。
答案 3 :(得分:-1)
我在C#中开发了一种状态驱动的串口编程语言,我相信它确实解决了每个人遇到的几乎所有串口问题。
请您尝试使用以下简单状态并检查内存泄漏吗?
state Init
recv();
$len = length($DATA_PACKET);
if("$len > 0") {
log($DATA_PACKET, Debug);
}
end state
如果您有任何疑问,请随时提出。