Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430

Выборка из List<byte>

12.03.2019, 15:14. Показов 3821. Ответов 40
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Имеется список формата - List<byte>. Требуется сделать выборку из лиса.
Найти 2 байта 0xA1, 0xA2 и взять все, что находится после и до 0xB1, 0xB2.
Пробовал Linq но фигня получалась.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
12.03.2019, 15:14
Ответы с готовыми решениями:

Конвертировать из byte[] в List<string> и обратно
Добрых времени суток. Собственно как переветс List&lt;string&gt; в byte, а потом наоборот. Нужно это для клиент серверного приложения.

Конвертировать из byte[] в List<object> и обратно
Софорумчане подскажите, а то совсем мозг не варит, начал так private byte ConvertTobyteArray(List&lt;object&gt; obj) { ...

Выборка из List
List&lt;int&gt; lint = new List&lt;int&gt;(); lint.Add(1); lint.Add(2); lint.Add(3); lint.Add(4); lint.Add(5); lint.Add(6); lint.Add(7); ...

40
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 08:46  [ТС]
Студворк — интернет-сервис помощи студентам
Wolfdp, спасибо за ответ. Но Ваш пример выдает исключение.

Дополнительные сведения: Коллекция была изменена; невозможно выполнить операцию перечисления.

Ругается на это foreach (var b in source)

Добавлено через 39 секунд
Скорее всего, это связано с таем, что коллекция постоянно пополняется. я об этом забыл сказать...

Добавлено через 7 минут
Элд Хасп, замена помогла ошибок нет.

Но есть несколько проблем. Моя вина в том, что я не сказал про то, что коллекция это List<byte> который всегда пополняется. Будет ли работать пример если искать нужно от 0xA1,0xA2, ....до...., 0xA1,0xA2?
В любом случае спасибо.

В Вашем примере была таже ошибка что и у примера выше (в момент, когда пытаюсь вернуть результат return byteByteA1A2B1B2.ToArray()
Дополнительные сведения: Коллекция была изменена; невозможно выполнить операцию перечисления.

Добавлено через 12 минут
Лист пополняется по 1 байту с интервалом 1-2 мс
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 11:31
Цитата Сообщение от hacker_007 Посмотреть сообщение
Но есть несколько проблем. Моя вина в том, что я не сказал про то, что коллекция это List<byte> который всегда пополняется. Будет ли работать пример если искать нужно от 0xA1,0xA2, ....до...., 0xA1,0xA2?
Это не проблема. Условия начала и конца указаны в строках 7 и 10, соответственно.

Цитата Сообщение от hacker_007 Посмотреть сообщение
Дополнительные сведения: Коллекция была изменена; невозможно выполнить операцию перечисления.
Каким образом меняется?
У Вас реализована многопоточность?
Если да, то методы LINQ не подойду, насколько знаю.
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 11:33  [ТС]
Элд Хасп, да, многопоточность. Из порта прут данные по 1 байту. (ReadByte)
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
13.03.2019, 11:36
юзайте for с оглядкой на Count. Если заполнение идет из другого потока, то подключайте синхронизацию.

Добавлено через 1 минуту
Цитата Сообщение от hacker_007 Посмотреть сообщение
Из порта прут данные по 1 байту. (ReadByte)
Вам нужно поймать сообщение?
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 11:38  [ТС]
Wolfdp, да. Я решил уйти от события datareceived ибо оно не успевает нормально работать с такой задержкой.И стал читать по одному байту. Теперь из этого всего пытаюсь собирать сообщение.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 11:48
Так как методы данного вычисления очень быстрые, то при многопоточности можно сделать так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        /// <summary>Объявлено на уровне класса или выше</summary>
        List<byte> bytes = new List<byte>() {/* Список байтов */ };
 
        List<byte> Range(ushort Begin, ushort End)
        {
            List<byte> ret; // Список для возврата
 
            byte Begin0 = (byte)Begin;
            byte Begin1 = (byte)(Begin >> 8);
            byte End0 = (byte)End;
            byte End1 = (byte)(End >> 8);
 
            // Получение сочетания последовательных байтов в анонимном типе
            var byteByte = bytes.Zip(bytes.Skip(1), (b0, b1) => new { b0, b1 });
 
            // Отсечение всех до Begin0, Begin1
            var byteByteA1A2 = byteByte.SkipWhile(bb => bb.b0 != Begin0 || bb.b1 != Begin1).Skip(1);
 
            // Получение всех до End0, End1
            var byteByteA1A2B1B2 = byteByteA1A2.TakeWhile(bb => bb.b0 != End0 || bb.b1 != End1).Select(bb => bb.b0);
 
            lock(bytes)
            {
                ret = byteByteA1A2B1B2.ToList();
            }
            return ret;
        }
1
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
13.03.2019, 12:00
Цитата Сообщение от hacker_007 Посмотреть сообщение
И стал читать по одному байту. Теперь из этого всего пытаюсь собирать сообщение.


Зачем? Вы в курсе что даже отправив 1 байт в порт, он не сразу улетает, а вполне себе может закешироватся, дождатся следующего байта и только тогда улететь? MTU вообще предпологает пакеты в 1500 (вроде).

Делайте нормальный Recive, если у вас TCP, то вообще можно смело использовать TcpClient и переходить на Stream делаете Read, анализируете полученый блок, если не весь -- дочитываете.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 12:01
Цитата Сообщение от hacker_007 Посмотреть сообщение
Я решил уйти от события datareceived ибо оно не успевает нормально работать с такой задержкой.И стал читать по одному байту. Теперь из этого всего пытаюсь собирать сообщение.
То есть у Вас есть поток байтов поступающий из внешнего устройства.
Есть индикаторы начала и конца сообщений в этом потоке.

Если да, то Вы неверно подошли к решению.
Метод получающий байт, должен проверять индикатор начала сообщения.
Если это начало сообщения, то подымается флаг накопления сообщения и создаётся буфер для накопления сообщения.
Остальные байту идут в буфер сообщения и проверяются на индикатор конца сообщения.
Как был отловлен конец сообщения, накопленное в буфере сообщение записывается в список (или очередь) готовых сообщений, и сбрасывается флаг накопления сообщения.
1
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
13.03.2019, 12:01
ради смеха -- отправляющая сторона тоже ваша?
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 12:11
Цитата Сообщение от hacker_007 Посмотреть сообщение
Я решил уйти от события datareceived ибо оно не успевает нормально работать с такой задержкой.
Я же правильно понял - Вы принимаете данные по COM порту от внешнего устройства?
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 12:22  [ТС]
Wolfdp, отправляющее устройство не мое.
Элд Хасп, да, данные по COM идут от внешнего устройства. Блин. Вот казалось бы элементарно. Дождаться стартовой последовательности. Ну мне это вообще в голову не приходило...

P.S. связь с устройством по RS-485
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 12:30
Цитата Сообщение от hacker_007 Посмотреть сообщение
Вот казалось бы элементарно. Дождаться стартовой последовательности.
Это один из стандартных методов разбора сообщения от медленных внешних устройств.

Забыл написать. Когда сообщение готово, то лучше не напрямую его записывать в список. Так другие части программы не смогут этого узнать.
Лучше генерировать событие в котором пересылать это сообщение. Кому надо - тот подпишется на это событие и будет обрабатывать новое сообщение.
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 12:43  [ТС]
Элд Хасп, я понял. Спасибо. Про событие. Пример можно? Ни раз так не делал.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 13:01
Цитата Сообщение от hacker_007 Посмотреть сообщение
Про событие. Пример можно? Ни раз так не делал.
Пример для случая с несколькими устройствами и, соответственно, несколькими объектами читающими из каждого устройства
В пространстве имён объявляете делегат
C#
1
2
        // Делегат
        public delegate void MessageBytesHandler(object sender, List<byte> message);
В классе который разбирает поток байтов на сообщения объявляете событие и для упрощения вызова события метод
C#
1
2
3
4
        // Событие
        public event MessageBytesHandler MessageBytesEvent;
        // Метод для вызова события
        public void OnMessageBytes(List<byte> message) => SignalEvent?.Invoke(this, message);
При создании объекта-приёмника (допусти имя receiver) подписываетесь на его событие.
C#
1
       receiver.MessageBytesEvent += receiver_MessageBytes;
В VS 2015 не знаю, но 2017 если после "+=" нажать два раза Tab, то метод с нужной сигнатурой будет создан автоматически.
Если нет, то сами создаёте метод.
C#
1
2
3
4
5
6
void  receiver_MessageBytes(object sender, List<byte> message)
{
  // Анализ полученного сообщения:
  // sender - это с какого приёмника поступило сообщение
  // message - список байтов сообщения
}
Добавлено через 2 минуты
При полном накоплении сообщения, вызываете метод OnMessageBytes с передачей в параметрах накопленных байт сообщения.
Это сообщение попадает в метод receiver_MessageBytes, который их обрабатывает.
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 13:02  [ТС]
Элд Хасп, ааа. Я понял. datareceived так же был реализован. Спасибо. Очень помогли. Сейчас буду делать.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 13:48
Цитата Сообщение от hacker_007 Посмотреть сообщение
datareceived так же был реализован.
Вы писали, что у Вас были проблемы из-за скорости выполнения datareceived.

Возможно это связанно с длительностью обработки полученного сообщения.
Поэтому получение байтов надо реализовывать в своём отдельном индивидуальном потоке. Чтобы это получение работало в реал-тайм.
При передаче собранного сообщения создавайте новый поток (явно или в асинхронном методе) и вызывайте событие в этом новом потоке.
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 14:59  [ТС]
Элд Хасп, да. Понял. Единственное, я не могу верную логику построить из-за того что старт посылки обозначается 2мя байтами... А заканчивается 2мя байтами CRC как оказалось далее.

Добавлено через 15 минут
Элд Хасп, точнее саму логику придумал. Но не могу реализовать именно "прямо" и надежно.

1. Т.к. старт посылки обозначается 2мя байтами, ждем первый из них, если приходит - записываем его.
2. Ловим следующий байт. Если это именно наш - второй стартовый, то проверяем есть ли в записи на нулевой позиции первый стартовый, если есть пишем на первую позицию второй стартовый и поднимаем флаг чтения.
3. В процессе чтения получаем байт в котором указывается длина информационной части пакета.
4. Узнаем общую длину пакета (инф. часть плюс служебная информация).
5. Пишем пакет до тех пор, пока он не будет равен рассчитанной длине.
6. Если дошли до такой длины берем CRC из пакета и сравниваем с рассчитанным CRC.
7. Если все норм то отправляем на обработку.

Добавлено через 2 минуты
Можно как нибудь алгоритм укоротить или более прямым сделать?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
13.03.2019, 15:39
Для подобных задач (где данные могут прийти не сразу, а частями, либо несколько пакетов склеенных в один) как раз и придумали System.IO.Pipelines

System.IO.Pipelines: High performance IO in .NET
1
191 / 29 / 8
Регистрация: 15.09.2011
Сообщений: 430
13.03.2019, 15:58  [ТС]
Ну вроде все сделал. Норм пашет. Нужно погонять это все.

Добавлено через 39 секунд
Someone007, ни раз не встречал. Сейчас гляну. Спасибо
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
13.03.2019, 16:28
Цитата Сообщение от hacker_007 Посмотреть сообщение
Можно как нибудь алгоритм укоротить или более прямым сделать?
Вряд ли.
Операции все быстрые, выполняются мгновенно.

Но обратите внимание на совет Someone007.
Задача получения данных по COM порту очень распространённая. Наверняка есть множество готовых решений. Возможно одно из них Вам подойдёт лучше чем Ваша собственная реализация.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.03.2019, 16:28

Выборка данных из List<T>
А подскажите как из списка вытащить нужные данные? как задать критерий? через foreach делать?

Выборка элемента по названию в List
привет. есть класс Myclass{ int kol; string name; } _Mass = new List&lt;Myclass&gt;(); содержит

Вывести данные из List (в листе структура Struct (в структуре данные формата int, short, byte) в textBox
Не выводятся данные

Ошибка. не получается устранить(list = List<byte>)
Вот накатал, но есть ошибки, никак не получается устранить(list = List&lt;byte&gt;): for (int j = 0; j &lt; list.Count; j++) ...

Поиск в списке массивов (List<byte[]>)
собственно в чем ошибка (Encoding роли не играет, он тут для читабельности) List&lt;byte&gt; btList = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru