Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447

TAP метод не выводит два последних значения в цикле

13.04.2018, 10:36. Показов 692. Ответов 0
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Есть метод async/await отправляющий сообщение и получающий ответ
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 private async Task GetCommandInfo(Lamp lamp)
        {
            if (lamp.Commands != null)
            {
                for (int i = 0; i < lamp.Commands.Count; i++)
                {
                    byte[] message = BitConverter.GetBytes(lamp.Commands[i].Code);//Формируем сообщение
 
                    tempMessage = await client.SendAsync(message,
                    lamp.ParentNode.PerentDevice.Address);//Отправляем сообщение
 
                    await NewMessageCheckNull(tempMessage);//Обрабатываем сообщения
                }
            }
        }
Ситуация выглядит так:
Результирующая структура данных получается чуть раньше, точнее на два последних сообщения меньше, чем необходимо. Это получается за счет того, что обработка сообщений начинается чуть позже чем отправка. Все время теряются два последних сообщения.

C#
1
2
3
4
5
6
7
8
9
        private async Task<bool> NewMessageCheckNull(ContainerRecivedMessage newMessage)
        {
            if (newMessage != null)
            {
                await Tod(tempMessage);
                return false;
            }
            return true;
        }
Tod это простая фабрика
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        private async Task Tod(ContainerRecivedMessage message)
        {
            RecivedPacket recived = await new CreatorRecived().GetNewRecivedInstanceAsync(message.OpCode.ToString(), message.Data);
            if (recived is Art)
            {
                Art art = recived as Art;
                Recived reciv = await new CreatorResponsePacket().CreatePacketAsync(art.Packet);
                if (reciv is ParametrDescription)
                {
                    ParametrDescription parametr = reciv as ParametrDescription;
                    Lamp lamp = await allDevices.GetLampByUidAsync(parametr.ManufactoryId, parametr.DeviceId);
                    parametr.Command.ParentLamp = lamp;
                    lamp.ChangeCommand(parametr.Command);
                }
 
            }
        }
C#
1
2
3
4
5
6
7
8
9
10
        public void ChangeCommand(Command changedCommand)
        {
            for (int i = 0; i < Commands.Count; i++)
                if (changedCommand.Code == commands[i].Code)
                {
                    Commands[i] = changedCommand;
                    break;
                }
 
        }
метод SendAsync
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public async Task<ContainerRecivedMessage> SendAsync(byte[] message, IPAddress recipientAddress, int delay = 300)
        {
            CancellationTokenSource stopRecive = new CancellationTokenSource();
            Task<ContainerRecivedMessage> result = new Task<ContainerRecivedMessage>(() => ReciveAsync(stopRecive.Token).Result);
            result.Start();
            Thread.Sleep(100);
            IPEndPoint endPoint = new IPEndPoint(recipientAddress, _port);
            await client.SendAsync(message, message.Length ,endPoint);
 
            Task delayTask = Task.Delay(delay);
            Task firstCompleted = await Task.WhenAny(result, delayTask);
            if (firstCompleted == delayTask)
            {
                await WaitReciveAllMessage(stopRecive, endPoint, delay);
                return null;
            }
            else
                return result.Result;
        }
Подскажите пожалуйста в чем проблема. Думал, что записывает в один и тот же экземпляр в этом месте в цикле:
C#
1
2
                    tempMessage = await client.SendAsync(message,
                    lamp.ParentNode.PerentDevice.Address);//Отправляем сообщение
Сделал так:
C#
1
2
                    await NewMessageCheckNull(await client.SendAsync(message,
                    lamp.ParentNode.PerentDevice.Address));
Вообще не получил ни одного значения. Не судите строго - это мои первые шаги в async/await. Спасибо

Добавлено через 46 минут
Как бы я нашел в чем проблема, но пока не знаю, как ее исправить. У меня действительно один экземпляр, для сохранения результата, а цепочка опроса довольно большая. Я вот не понимаю почему если я создаю новый экземпляр для временного хранения данных и присваиваю ему выражение await client.SendAsync(...); то при вызове методы
await NewMessageCheckNull(...); в него попадают данные из предыдущего сообщения и не важно какой экземпляр ему передавать. Как так происходит?
Причина в гонке данных, пакеты приходят с задержкой и он в цикле обрабатывает ровно столько сколько нужно, но вот получает предыдущие. Можно конечно очередь сделать на прием сообщений, что вообще и нужно сделать, но вопрос почему все равно висит в воздухе)

Добавлено через 9 минут
C#
1
2
3
4
5
6
7
8
9
10
11
12
        private async Task GetDevicesInfo()
        {
            for (int i = 0; i < allDevices.Devices.Count; i++)
            {
 
                tempMessage = await client.SendAsync(...);
                await NewMessageCheckNull(tempMessage);
 
                await CheckDeviceInfo(i);
 
            }
        }
Скорей всего проблема вот тут. Я в ответ должен получить 4 сообщения вместо одного, а получаю одно.
Метод ReciveAsync:
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
        private async Task<ContainerRecivedMessage> ReciveAsync(CancellationToken cancelRecive)
        {
            try
            {
                DataRecived data = new DataRecived();
                IPEndPoint endPoint = null;
                while (!cancelRecive.IsCancellationRequested)
                {                   
                    data.buffer = client.Receive(ref endPoint);
                    if (endPoint != client.Client.LocalEndPoint && data.buffer.Length > 13)
                    {
                        OpCodes sentOpCode = (OpCodes)data.buffer[9];
                        if (IsCorrectReciveOpCode(sentOpCode.ToString()) || !IsCorrectOpCode(sentOpCode.ToString()))
                        {
                            return new ContainerRecivedMessage(endPoint, sentOpCode, data);
                        }
                    }
                }
                return null;
            }
            finally
            {
                //client.Close();
            }
        }
Что происходит в данном случае, если метод успеет принять четыре сообщения, а SendAsync возвращает Task<ContainerRecivedMessage>? Куда денутся 3 оставшихся задачи?

Добавлено через 16 часов 14 минут
Проблему нашел. Это мои кривые ручки сокет написали. Если вдруг кому интересно, то проблема в непраильной организации пакетов и отправка закрывается только по истечению таймаута, а если он не истекает, то приходят сообщения, которые стоят в очереди и я их получаю, при следующей отправке сообщения, а новое помещается в конец очереди. Значит займусь очередью.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.04.2018, 10:36
Ответы с готовыми решениями:

Метод Ньютона-Рафсона. Программа не выводит значения
Написал программу(как смог) для решения системы нелинейных уравнений методом ньютона-рафсона. Исходная система: sin(x1+0.5)-x2=0; ...

Написать метод, который вычисляет значения функций и выводит таблицу их значений
Здравствуйте, нужно написать метод который вычисляет значения x=sin (a) и y=cos (a). Вывести таблицу значений от -Пи до Пи с шагом Пи/4. ...

Написать метод, который вычисляет значения функций и выводит таблицу их значений
Помогите решить. Проблема в методах? Что должно быть в них, вместо того что есть? Условие: написать метод который вычисляет значения...

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.04.2018, 10:36
Помогаю со студенческими работами здесь

Написать метод, который вычисляет значения функций и выводит таблицу их значений
написать метод который вычисляет значения x=sin (a) и y=cos (a). Вывести таблицу значений от -Пи до Пи с шагом Пи/4.

ввести слово.вывести два первых и два последних символа через тире
помогите пожалуйста!!!!!оооочень прошу!!! вот задача: ввести слово.вывести два первых и два последних символа через тире Заранее...

Дан массив размера N. Вывести его элементы в порядке: два последних, два первых и т.д
Дан массив размера N. Вывести его элементы в порядке: два последних, два первых и т.д. Такая вот задача. Помогите, пожалуйста.

Программа, которая выводит N последних элемента списка
Добрый день! Имею проблему с написанием простой программы, которая заключается в том, что есть список с любыми элементами и нужно, чтобы на...

не выводит в цикле
не могу вевести в цикле из базы id. тоесть надо чтоб выводило из базы все ид по 20шт за раз нтоесть шаблон должен быть в 20 ид но если...


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

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru