Непонятно с async-await в C# - 2
Так я и так не читаю больше, чем dataReadSize.Нет, data.Count <=N
Если вы имеет ввиду ограниченный буфер, куда все пришедшие данные складируются, то можно использовать что-то вроде кольцевого буфера - т.е. перезаписываемого с начала, когда буфер заполнен. Тут нужно только успевать считывать, чтобы данные не накапливались. Тогда в код считывания с такого буфера нужно просто добавить логику, перебрасывающую чтение очередного пакета данных с конца на начало - это просто, т.к. размеры буфера и считываемого пакета известны.
Кольцевые буферы много где применяются. Например, на портах, вроде, так устроено - буферы там довольно ограниченные, и они перезаписываются с начала, когда достигнут конца. Ещё я использовал кольцевой буфер на графике, который в реальном времени показывал ход эксперимента. Там и всплыла проблема WPF - окошко графика не можно отрисовать более примерно 10-15к точек в секунду. Т.е. на графике только оси координат и обозначения, которые постоянны и не меняются, и постоянно добавляющиеся данные эксперимента в виде точек, соединённых линиями - больше ничего. Если хочешь, чтобы график обновлялся хотя бы 5-8 раз в секунду, то больше 1-2к точек не показывай. Т.е. накопление данных на графике не подходило никак - пришлось воспользоваться "бегущим" графиком через кольцевой буфер (взял из поставки графика, а не сам написал). Всё равно там пришлось городить систему оптимизации данных, посылаемых на отрисовки, которая брала не все данные, а, скажем, каждое 5, и только его отрисовывало. Ну и не тупо каждое 5, а с сохранинем экстремумов, чтобы не пропускать максимальные и минимальные значения, которые важны оператору, проводящему эксперимент. Вобщем, довольно навороченная и настраеваемая система оптимизации по данным была (для всего - для приёма с устройства, для отрисовок, для расчёта и прочего).
Но это не подходит в случае, когда нужно хранить данные всего эксперимента. Тогда нужно либо сбрасывать на ROM, либо ещё куда, чтобы потом можно было достать (с соответствующим замедлением обработки, конечно).
В моём случае скорость поступления данных была в максимуме где-то около 10000 4-байтовых (int) значений в секунду. Эксперимент длится в пределе минут 5 (это с кратным запасом) - т.е. это 10000 значений * 4 байт * 60 секунд * 5 минут = 12М байт. Из-за особенностей расчёта эти данные с разными перерасчётами дублировались на разных слоях раз 10 - т.е. в сумме 120М байт в RAM. Ну и на всё остальное сколько-то памяти нужно - вобщем, в 400-500М байт я укладывался за 5 минут работы программы. Если не оставлять программу включенной постоянно, то вылетать с переполнением памяти не будет. Правда, при 10к данных в секунду у меня уже тормозил процессор и расчёт. Да и такая точность была не нужна. Там по сути много данных шло из-за того, что нужно было определять обороты в минуту, а для этого использовались метке на вращающемся теле. Меток должно было быть в пределах 50-400 (в идеале - чтобы было видно профиль работы каждого цилиндра двигателя в одном обороте, если двигатель многоцилиндровый). На реальных двигательных установках скорость вращения не превышала 10к оборотов в минуту (166 в секунду). Т.е. теоретический максимум был 33к метки (т.е. 4-байтовых данных) в секунду, но это прям вообще теоретический. Реалистичный максимум не превышал 4-5к в секунду. Да и задачи, чтобы подходило подо все возможные обороты в мире не ставилось. Т.е. всякие "формулы 1" с их 15-19 rpm и ракетные топливные турбины с их, доходящими до 100к rpm не рассматривались. Основные клиенты были - сельхозтехника, электротурбины и дизели, где обороты куда скромнее.
Если оставить за кадром всё остальное, то да.
Синхронизации и блокировки тормозят процесс работы с данными. Т.е. весь объём времени по сути делится между числом потоков, и каждый поток может работать с этими данными не больше, чем время, оставшееся от работы других потоков. А мне надо было, чтобы задержек не было, чтобы было быстро. Тут палка о двух концах - либо блокировки и синхронизации с неизбежным ожиданием очереди на работу с данными, либо одновременный доступ с осуществлением "потокобезопасности" другими способами, типа специальной организации доступа к данным, когда потоки не будут друг другу мешать. Сделать и то, и то одновременно невозможно. Разве что пойти способом, подобным рэйд-массивам в системах хранения данных - т.е. делать копии данных и возволять работать потокам с этими копиями. Но это надо делать систему синхронизации копий, а кроме того, у нас не получится чистый рэйд, т.к. физический источник будет всё равно один - общая RAM, ну и узким местом будет интерфейс доступа к этой RAM. Вобщем, выходы наверняка есть, но не тривиальные.