SerialPort SerialStream 在读取循环中泄漏内存

SerialPort SerialStream leaking memory in read loop

我正在尝试使用以下方法从串口连续读取数据:

var serialPort = new SerialPort("COM7", 38400, Parity.None, 8, StopBits.One);

var buffer = new byte[256];

Action read = null;

AsyncCallback callback = delegate (IAsyncResult ar)
{
    int len = serialPort.BaseStream.EndRead(ar);

    // do something with data

    read();
};

read = delegate
{
    serialPort.BaseStream.BeginRead(buffer, 0, buffer.Length, callback, null);
};

serialPort.Open();

while (true)
{
    read();

    //Thread.Sleep(100);
}

以下对象的数量不断增加会导致内存泄漏:

即使在垃圾回收通过后,对象仍然存在。

上面的示例是一个最小的可重现示例。我已经删除了 "do something with data",因为问题发生时有或没有任何数据处理。

while循环中的Thread.Sleep只是减慢了内存消耗。我已将其遗漏,以便清楚地显示问题。以上示例在我的机器上将在 20 秒内消耗大约 650mb。

.NET Core 3.1 和 .NET Framework 4.8 都会出现该问题。

我确定我做错了什么,我现在看不到它是什么。

This leaks memory with an ever-increasing...

很简单,因为您在现有操作完成之前无限循环 BeginRead 操作:

while (true)
{
    read(); // <-- this delegate calls `BeginRead` thus starting ANOTHER verlapped read operation

    //Thread.Sleep(100);
}

将其更改为:

serialPort.Open();
read(); // kick off initial read

while (/* some condition*/)
{
}

// quit

您的回调通过确保仅在先前完成后才开始另一个重叠读取操作来做正确的事情:

AsyncCallback callback = delegate (IAsyncResult ar)
{
    int len = serialPort.BaseStream.EndRead(ar);

    // do something with data

    read(); // <--- correctly initiates another read since the existing is complete
};