2011-01-18 3 views
1

У нас есть код последующих C# для нашего последовательного порта связи:последовательный порт связи накапливают большое количество запущенных потоков

   ProcCntrlSSPort = new SerialPort(portNumber, 115200, Parity.None, 8, StopBits.One); 

       ProcCntrlSSPort.Handshake = Handshake.None; 
       ProcCntrlSSPort.ReadTimeout = 10; 
       ProcCntrlSSPort.ReadBufferSize = 32768; 
       ProcCntrlSSPort.DataReceived += ProcCntrlSSPortDataReceived; 
       //ProcCntrlSSPort.DataReceived += new SerialDataReceivedEventHandler(ProcCntrlSSPortDataReceived); 
       ProcCntrlSSPort.ReceivedBytesThreshold = 1; 
       try 
       { 
        ProcCntrlSSPort.Open(); 
        ProcCntrlSSPort.DiscardInBuffer(); 
       } 

Каждый 100 мс, есть сообщение о состоянии получено нашим приложением. Я понимаю, когда SerialPort получил ReceivedBytesThreshold количество байтов, событие будет запущено SerialPort. Мы должны использовать 1 для ReceivedBytesThreshold, потому что одна из наших важных данных отправляется по 1 байт каждый раз, когда этот байт доступен.

Когда событие запускается SerialPort и обрабатывается получателем, это событие должно быть удалено, и поток, связанный с этим событием, должен быть доступен для следующего использования. поэтому не должно быть большого количества скопившихся потоков.

Но я обнаружил, что работающие потоки будут непрерывно увеличиваться с 20 потоков до более чем 400 потоков после ночной. Просто сообщение о состоянии отправляется в наше приложение, тогда никаких других действий. Я отключил весь код процесса, поэтому я уверен, что накопленные потоки НЕ относятся к нашему коду. Это означает, что мы ничего не делаем по полученным данным для целей тестирования.

Я увеличил ReceivedBytesThreshold, заявив 128, для целей тестирования. Это замедлит накопление, но количество потоков все равно медленно растет. почему .net framework не может правильно обрабатывать свои потоки? Или я не использовал его правильно?

+1

Ummmm. Не звучать умно-алексей, но не для .NET Framework правильно обрабатывать протектор, это зависит от разработчика. У нас есть приложение для сканирования, которое обрабатывает тысячи купонов в день по последовательному порту и не имеет проблем. Вы правильно исследовали связь с последовательным портом с .NET, чтобы понять, что вы делаете и что происходит? Threading сложный, и вы не можете рассчитывать на это, не понимая его больше, чем вы ожидали бы, чтобы безопасно управлять автомобилем в большом городе, не изучая правила дорожного движения. – David

+0

Вы хотите создать потоки в функции 'ProcCntrlSSPortDataReceived'? Не могли бы вы разместить то, что вы там делаете? Вероятно, проблема заключается в том, где вы создаете потоки. – SwDevMan81

+0

мы не использовали собственный поток для обработки последовательного порта. Я думаю, что класс SerialPort .Net создает поток для обработки последовательного порта. – 5YrsLaterDBA

ответ

2

How does SerialPort handle DataReceived объясняет, что может случиться.

Похоже, что вызовы DataReceived будут использовать ThreadPool и вызовы QueueUserWorkItem. Это означает, что если вы не будете обрабатывать данные достаточно быстро, вызовы могут стоять в очереди, как вы видите.

Если вы хотите сохранить счетчик вниз (как тест), вы можете попробовать и прочитать все байты после получения события с помощью BytesToRead, а затем «обработать» каждый прочитанный символ. Другой вариант, который предлагается в этой статье, - создать собственный «процесс обработки» для обработки, когда вы получаете данные.

Это также выглядит, как вы можете установить максимальное количество потоков, созданных в ThreadPool с помощью ThreadPool.SetMaxThreads

Устанавливает количество запросов в пул потоков, которые могут быть активными одновременно. Все запросы выше этого числа остаются в очереди до тех пор, пока потоки пула потоков не станут доступными.

Но все это будет означать изменение ситуации, когда происходит очередность. В конечном счете вы должны решить, почему он отстает.

1

Как сказал SwDevMan81, DataReceived (как и многие другие асинхронные события в .NET) запускается в потоке ThreadPool. Есть несколько вещей, которые вы не должны делать в потоках ThreadPool, а главное: не ждите чего-либо, т. Е. Не используйте операции блокировки файла, не используйте WaitForSingleObject, не используйте ISynchronizeInvoke.Invoke, если вы не используете уверен, что он не будет блокироваться (надолго). В противном случае ThreadPool просто запустит новый поток, когда новый рабочий элемент будет выставлен в очередь, пока он не достигнет предела ThreadPool.MaxThreads (что смехотворно высоко, IIRC).

Самый простой способ узнать, является ли ваша проблема проблемой ThreadPool.GetAvailableThreads - если она со временем уменьшается, тогда вы должны написать собственный поток для обработки данных и просто поместить его в потокобезопасную очередь в ProcCntrlSSPortDataReceived.

Смежные вопросы