Производительный приём данных в отдельном потоке - C#

Узнай цену своей работы

Формулировка задачи:

Как грамотно организовать приём данных от внешнего устройства? Внешнее устройство Cypress FX3 USB 3.0 режим Bulk, способно выдавать данные со скоростью до 200MB/s, источник данных умеет притормаживать выдачу, если буфер в Cypress FX3 занят. Приём данных идет в отдельном потоке с помощью конкурентной очереди. Скорость не удовлетворительная и сильно прыгает от 10 до 70MB/s.
Листинг программы
  1. public void ListenerThread()
  2. {
  3. inBuf = new byte[BulkInEndPt.MaxPktSize];
  4. BulkInEndPt.TimeOut = CyConst.INFINITE;
  5. Print.BeginInvoke("ADC Listener started. MaxPktSize = " + BulkInEndPt.MaxPktSize + ", Address = 0x" + BulkInEndPt.Address.ToString("X2"), null, this);
  6. startedEvent.Set();
  7. while (true)
  8. {
  9. buf_size = inBuf.Length;
  10. bResult = BulkInEndPt.XferData(ref inBuf, ref buf_size);
  11. if (bResult && buf_size != 0)
  12. {
  13. Program.afifo.Enqueue(inBuf.Take(buf_size).ToArray()); // copy
  14. NewData.BeginInvoke(pack_cnt++, null, null, this);
  15. //Print.BeginInvoke("ADC listener recieved " + buf_size + " bytes. Read result: " + bResult, null, this);
  16. }
  17. }
  18. }
Основной поток обработки дергается асинхронно с помощью BeginInvoke и выбирает данные из FIFO, если они там есть (аналог прерывания от потока слушателя). Изначально я пробовал использовать BeginInvoke и lock в основном потоке, но оказалось, что пакеты таким способом путаются и приходят в основной поток не в порядке их прихода по USB. Конкурентное FiFO объявлено таким образом:
Листинг программы
  1. public static ConcurrentQueue<byte[]> afifo = new ConcurrentQueue<byte[]>();
Возможности задавать начальное capacity у класса нет - но оно хранит только ссылки на массивы байт

Решение задачи: «Производительный приём данных в отдельном потоке»

textual
Листинг программы
  1.                 if (bResult && buf_size != 0)
  2.                 {
  3.                     byte[] bytes = new byte[buf_size];
  4.                     Array.Copy(inBuf, bytes, buf_size);
  5.                     Program.afifo.Enqueue(bytes);
  6.  
  7.                     NewData.BeginInvoke(pack_cnt++, null, null, this);
  8.                 }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

10   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы