C# 使用.net SerialPort进行内存泄漏,有更好的方法吗?

C# 使用.net SerialPort进行内存泄漏,有更好的方法吗?,c#,.net,serial-port,C#,.net,Serial Port,我有一个通过rs232与硬件对话的程序。该软件用于显示从硬件通过rs232推送的数据流,并以尽可能快的速度显示。我遇到的问题是,随着时间的推移,分配给程序的私有内存会爆炸,并会很快使程序崩溃。如果我在大约2分钟内禁止硬件发送数据,那么软件可以清除内存,但前提是我暂停数据流 我使用的是来自SerialPort的DataReceived事件,这似乎就是问题所在,因为即使DataReceived函数在其中什么都不做,它也会导致内存峰值。我能想到的唯一一件事是,每次引发此事件时,它都会创建一个新线程来运

我有一个通过rs232与硬件对话的程序。该软件用于显示从硬件通过rs232推送的数据流,并以尽可能快的速度显示。我遇到的问题是,随着时间的推移,分配给程序的私有内存会爆炸,并会很快使程序崩溃。如果我在大约2分钟内禁止硬件发送数据,那么软件可以清除内存,但前提是我暂停数据流

我使用的是来自SerialPort的DataReceived事件,这似乎就是问题所在,因为即使DataReceived函数在其中什么都不做,它也会导致内存峰值。我能想到的唯一一件事是,每次引发此事件时,它都会创建一个新线程来运行,而且它发生得如此之快,以至于当数据进入时,计算机没有时间运行GC

有没有更有效的方法从SerialPort对象中提取数据?当我收到“换行”时,我只关心字符串

谢谢


John Vickers

接收的数据在不同的线程上执行。我在使用快速数据时遇到了问题,这一事件给我带来了问题。因此,我创建了一个线程并自己读取数据:

while (this.serialPort.IsOpen)
{
    int b = this.serialPort.ReadByte();
    if (b != -1)
    {
        // data is good here
    }
}

但正如其他人所说,没有任何代码示例,我们就没有什么可以帮助您的。

我用C语言开发了一种状态驱动的串行端口编程语言,我相信它确实解决了几乎所有人都会遇到的串行端口问题

请您尝试以下简单状态并检查内存泄漏,好吗

state Init
  recv();
  $len = length($DATA_PACKET);
  if("$len > 0") {
    log($DATA_PACKET, Debug);
  }
end state

如果您有任何问题,请随时提问。

这很不寻常,但在技术上是可能的。SerialPort使用线程池线程调用DataReceived事件处理程序。一旦收到一个或多个字节,它就会抓取一个TP线程来通知您的应用程序。事件生成代码中有一个锁,一次只能有一个线程调用事件处理程序

这里的一个潜在故障模式是,其中一个调用(可能是第一个调用)进入代码中的一个循环,而该循环从未退出。如果您没有设置握手属性,设备可以继续发送和触发更多TP呼叫,所有这些呼叫都会阻塞该锁

从“调试+窗口+线程”窗口诊断此问题。如果我的猜测是准确的,那么你应该看到这里列出了大量的线程。其中一个应该在DataReceived事件处理程序中,双击它并查看调用堆栈以查看它被卡住的位置。您看到的内存被这些线程的堆栈占用,每个线程占用1兆字节

另一种可能是DataReceived事件处理代码非常慢,可能是通过调用Control.Invoke()实现的。速度慢到无法跟上设备的速度。现在确实需要使用握手属性来设置流控制。或者修复任何让它变慢的东西。顺便说一句,还应该有大量的ErrorReceived事件,一定要实现它,这样你就可以看到这些错误了


可以同时运行的TP线程数有一个上限。这是相当慷慨的,250倍的核心数量。在一台典型的双核机器上,这很容易消耗半GB的内存。

只是为了解决这个问题

在使用DataReceived事件时,我看到大量内存泄漏

我使用的是USB 3G调制解调器,它提供串行调制解调器接口。我编写了一个小程序,它只打开串行端口并连接到DataReceived事件。事件处理程序只是一个空方法

如果你拔掉加密狗,内存开始以每秒10MB的速度泄漏。没有抛出异常


旋转一个新线程并使用同步读取(…)方法为我解决了这个问题。现在,当我拔出我可以处理且没有内存泄漏的加密狗时,我会遇到一个例外。

尝试分享一些示例代码-您的问题并不完全清楚。“尽可能快”的速度有多快?您的项目看起来不错,但实际上没有多少东西可以开始。如果可能的话,我也不想对我的软件进行重大修改。你不需要对你的软件进行重大修改。您可以将驱动程序作为.NET应用程序的一部分进行重新分发,请参阅以下有关如何执行此操作的线程。谢谢你的建议,这是我最后的选择。一旦我创建了一个线程,它总是在后台检查,而不是使用DataReceived事件,它再次工作得很好!好的,什么是真正的快速数据?我使用的DataRcvd事件处理程序速度高达1Mbps,单核,1.8Ghz,没有问题。我在与Arduino接口时发现了完全相同的问题,并使用了非常类似的解决方案,尽管是在不同的线程上(如下面Jared的回答)。所选答案列出的AnySerialPort.com网站已不存在,这是一个更简单的解决方案。我刚才遇到了相同的问题,该线程帮助了我。当我使用DataReceived事件处理程序(.NET 3.5)时,即使我只是读取处理程序中的端口并丢弃字节,线程和专用内存的数量也会不断增加,并且很快,在几个小时内,程序会因“内存不足异常”而崩溃。因此,我最终使用了自己的后台线程(使用backgroundworker),只需在循环中读取内容。问题消失了!我想知道.NET4是否有这个问题。但我还没有检查。