我有一个嵌入式debian板,单声道运行.NET 4.0应用程序,具有固定数量的线程(没有操作,没有任务)。由于内存问题,我在Windows中使用CLR-Profiler来分析内存堆。 下面的图表现在显示,IThreadPoolWorkItems没有(至少不在第0代)收集:
现在,我真的不知道这些物品可能在哪里使用以及它们为什么不被收集。
修改
...
private Dictionary<byte, Telegram> _incoming = new Dictionary<byte, Telegram>();
private Queue<byte> _serialDataQueue;
private byte[] _receiveBuffer = new byte[2048];
private Dictionary<Telegram, Telegram> _resultQueue = new Dictionary<Telegram, Telegram>();
private static Telegram _currentTelegram;
ManualResetEvent _manualReset = new ManualResetEvent(false);
...
// Called from other thread (class) to send new telegrams
public bool Send(Dictionary<byte, Telegram> telegrams, out IDictionary<Telegram, Telegram> received)
{
try
{
_manualReset.Reset();
_incoming.Clear(); // clear all prev sending telegrams
_resultQueue.Clear(); // clear the receive queue
using (token = new CancellationTokenSource())
{
foreach (KeyValuePair<byte, Telegram> pair in telegrams)
{
_incoming.Add(pair.Key, pair.Value);
}
int result = WaitHandle.WaitAny(new[] { token.Token.WaitHandle, _manualReset });
received = _resultQueue.Clone<Telegram, Telegram>();
_resultQueue.Clear();
return result == 1;
}
}
catch (Exception err)
{
...
return false;
}
}
// Communication-Thread
public void Run()
{
while(true)
{
...
GetNextTelegram(); // _currentTelegram is set there and _incoming Queue is dequeued
byte[] telegramArray = GenerateTelegram(_currentTelegram, ... );
bool telegramReceived = SendReceiveTelegram(3000, telegramArray);
...
}
}
// Helper method to send and receive telegrams
private bool SendReceiveTelegram(int timeOut, byte[] telegram)
{
// send telegram
try
{
// check if serial port is open
if (_serialPort != null && !_serialPort.IsOpen)
{
_serialPort.Open();
}
Thread.Sleep(10);
_serialPort.Write(telegram, 0, telegram.Length);
}
catch (Exception err)
{
log.ErrorFormat(err.Message, err);
return false;
}
// receive telegram
int offset = 0, bytesRead;
_serialPort.ReadTimeout = timeOut;
int bytesExpected = GetExpectedBytes(_currentTelegram);
if (bytesExpected == -1)
return false;
try
{
while (bytesExpected > 0 &&
(bytesRead = _serialPort.Read(_receiveBuffer, offset, bytesExpected)) > 0)
{
offset += bytesRead;
bytesExpected -= bytesRead;
}
for (int index = 0; index < offset; index++)
_serialDataQueue.Enqueue(_receiveBuffer[index]);
List<byte> resultList;
// looks if telegram is valid and removes bytes from _serialDataQueue
bool isValid = IsValid(_serialDataQueue, out resultList, currentTelegram);
if (isValid && resultList != null)
{
// only add to queue if its really needed!!
byte[] receiveArray = resultList.ToArray();
_resultQueue.Add((Telegram)currentTelegram.Clone(), respTelegram);
}
if (!isValid)
{
Clear();
}
return isValid;
}
catch (TimeOutException err) // Timeout exception
{
log.ErrorFormat(err.Message, err);
Clear();
return false;
} catch (Exception err)
{
log.ErrorFormat(err.Message, err);
Clear();
return false;
}
}
谢谢你的帮助!
答案 0 :(得分:0)
我发现,就像已经提到的消费者一样,&#34;问题&#34;是通过SerialPort进行通信。我找到了一个有趣的话题here:
SerialPort有一个等待事件的后台线程(通过WaitCommEvent)。每当一个事件到来时,它就会对一个线程池工作进行排队 可能导致调用事件处理程序的项目。让我们关注一下 其中一个线程池线程。它试图锁定(快速 原因:存在将事件提升与结束同步;对于 更多细节见最后)一旦获得锁定,它会检查是否 可读的字节数高于阈值。如果是这样, 它会调用你的处理程序。
所以这个锁是你的处理程序不能单独调用的原因 线程池线程同时进行。
这肯定是他们不能立即收集的原因。我也尝试过不在我的SendReceiveTelegram方法中使用阻塞Read,但是使用SerialDataReceivedEventHandler导致了相同的结果。
所以对我来说,我会保留现状,除非你给我一个更好的解决方案,这些ThreadPoolWorkitems不再在队列中保留那么久。
感谢您的帮助以及您的负面评估:-D