GC 未收集 IThreadPoolWorkItem

IThreadPoolWorkItem not collected by GC

我有一个带有单声道的嵌入式 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;
        }
    }

谢谢你的帮助!

我发现,就像已经提到的 spender 一样,"issue" 是通过 SerialPort 进行的通信。我发现了一个有趣的话题 here:

SerialPort has a background thread that's waiting for events (via WaitCommEvent). Whenever an event arrives, it queues a threadpool work item that may result in a call to your event handler. Let's focus on one of these threadpool threads. It tries to take a lock (quick reason: this exists to synchronize event raising with closing; for more details see the end) and once it gets the lock it checks whether the number of bytes available to read is above the threshold. If so, it calls your handler.

So this lock is the reason your handler won't be called in separate threadpool threads at the same time.

这肯定是他们没有立即收集的原因。我还尝试在我的 SendReceiveTelegram 方法中不使用阻塞读取,而是使用 SerialDataReceivedEventHandler 导致相同的结果。

所以对我来说,我会保持原样,除非你给我带来更好的解决方案,这些 ThreadPoolWorkitems 不再在队列中保留那么久。

感谢您的帮助以及您的负面评价:-D