Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: потоки? помогите ещё раз  (Прочитано 32785 раз)
0 Пользователей и 6 Гостей смотрят эту тему.
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« : 02-07-2012 10:04 » new

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

Задача такая:

Надо читать из прибора, из его 3 внутренних буферов по 512 байт информацию и выводить в свою часть экрана.
До тех пор пока на экране не будет нажата, к примеру, кнопка.

Информация в буферах всё время пишется с 0 до 511, и опять с 0.

Создавать 3 потока?
Вывод на экран через CEDIT медленный, как по-другому?

Джон, Алексей153 и все-все-все помогите Не понял А то вдруг в отпуск не отпустят Жаль
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #1 : 02-07-2012 10:12 » 

ann_nef, а зачем тут потоки? в простейшем случае:
пока (не нажата кнопка на экране) цикл
  читаем первый внутренний буфер прибора
  выводим информацию в область экрана для первого буфера прибора
  читаем второй внутренний буфер прибора
  выводим информацию в область экрана для второго буфера прибора
  читаем третий внутренний буфер прибора
  выводим информацию в область экрана для третьего буфера прибора
конец цикла
Записан
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #2 : 02-07-2012 10:47 » 

Может и так. Тем более, что бесконечное обновление-запись буферов скорее всего заменится конечным, как я только что выяснила у начальника.

Добавлено через 1 час, 20 минут и 58 секунд:
И всё-таки надо использовать сообщения и\или потоки.
Запустили n-раз сценарий, получили ответ,который <512 байтов --> вывели информацию на экран --> запустили сценарий и тд
« Последнее редактирование: 02-07-2012 12:08 от ann_nef » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 02-07-2012 12:12 » 

ann_nef, а зачем потоки-то? Неужели устройство настолько быстро пишет в память, что только многоядерный процессор справится с чтением буфера? Не верится что-то, да и на экране это прочитать явно не успеешь.

Если весь смысл в том, что устройство, напротив, пишет очень медленно, -- так, при наличии возможности прочитать частями, можно хоть по 1 байту за итерацию цикла вычитывать: как только устройство сбросило байт в один из буферов, прочитали и отобразили, в общем цикле.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 02-07-2012 12:15 » 

У меня вопрос: как узнать, что устройство изменило буфер и как найти измененные байты? Или буфер рассматривается как единая сущность и каждый раз считывается целиком?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 02-07-2012 12:48 » 

Отпуск - это святое. Конечно поможем.

ann_nef, что значит "Вывод на экран через CEDIT медленный"?

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

Итак, начнём с одного буфера (ессно, что два остальных будут работать аналогично). Вопрос "как узнать" уже RXL задал, поэтому повторяться не буду. В любом случае у тебя есть два варианта: 1. приходит некое сообщение об изменении состояния буфера (возможно даже с доп. инфой); 2. ты сама периодически опрашиваешь буфер, на предмет изменения состояния (тн polling).

Если данные в буфере (приходящие из буфера) меняются очень быстро, но их немного, то я бы посоветовал сделать в проге FIFO буфер, который бы накапливал данные, а модуль отображения забирал бы их из него большими кусками.

Ну как-то так. Для более детального ответа не хватает... деталей в вопросе. Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #6 : 03-07-2012 05:25 » 

По мере разговоров с постановщиком задачи, задача несколько упрощается.

Как сформулировал RXL: " буфер рассматривается как единая сущность и каждый раз считывается целиком".

Т.е. всё сводится к такому алгоритму без деталей:
1. запуск сценария
2. задержка длительностью необходимой для получения ответа и заполнения буферов(это время мне известно)
3. чтение буфера
4 вывод буфера
5 переход к п.1
И так продолжается до тех пор пока не нажмут на кнопку "Прекратить".

Сейчас у меня остался вопрос только как событие "нажатие кнопки" сделать условием цикла. Здесь была моя ладья...
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 03-07-2012 06:12 » 

ann_nef, вопросы:
1. Все три буфера заполняются одновременно?
2. Период чтения буферов лимитирован?
3. Периодичность цикла наполнения/чтения всех буферов лимитирована?
4. Интерфейс с устройством какой?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #8 : 03-07-2012 06:52 » 

RXL, ответы:
1. Все три буфера заполняются одновременно - это ответ по трём CAN каналам.
2. нет
3. нет
  сценарий запускается однократно, через какое-то время получается ответ и можно с ним работать до следующего запуска сценария, инфа в буфере до след.запуска не меняется.
4. устройство подключено к сом-порту.

Но, к устройству подключена плата, которая тестируется, и она отвечает на сценарий, а эти ответы фиксирует уст-во, записывая во внутренние буферы ПЛИС.
А  с устройством через СОМ-порт общается моя программа.


Если не вдаваться в подробности и абстрагироваться от конкретной задачи ,то всё сводится к двум проблемам:

1. как прекратить бесконечный цикл
2. что лучше использовать для вывода экран CEDIT, CListBox

1 вопрос - главный.

Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 03-07-2012 06:59 » 

Цитата
1. как прекратить бесконечный цикл
По нажатию кнопки
типа
while (!kbhit()) {

...
}

Добавлено через 6 минут и 33 секунды:
Конечно, это и правильно и неправильно.
Правильно, если программа занимается только  считыванием и выводом.

Неправильно - если еще что-то делается.

В неправильном случае нужно взводить свой собственный флаг

Если говорить о независимых потоках

1. Функция обработки  нажатия клавиши. Взводим флаг
2. Функция чтения буфера
   Проверка флага
       Или прекратить сразу, или закончить ввод
3. Функция вывода
   проверка флага
       Или прекратить сразу, или закончить вывод
« Последнее редактирование: 03-07-2012 07:06 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #10 : 03-07-2012 08:47 » 

Sla,
while (!kbhit()) {

...
}

не подходит
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 03-07-2012 09:16 » 

ann_nef, а зачем, всё-таки, бесконечный цикл?
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 03-07-2012 09:34 » 

1. как прекратить бесконечный цикл
2. что лучше использовать для вывода экран CEDIT, CListBox

1 вопрос - главный.


1.
Судя по некоторым вторичным половым признакам (CEDIT, CListBox) у тебя какое-то MFC-шное оконное приложение, хотя лучше всего это явно указывать с самого начала, тогда не будт непоняток типа kbhit().
Итак, у тебя крутится цикл, и ессно вся программа "спит". Обработка сообщений невозможна. Даже, если ты нажимаешь кнопки, их сообщения помещаются в очередь, но из неё не достаются и не обрабатываются. Для этого есть такой трюк. Допустим в обработчике OnKeyDown (или по нажатию кнопки, или по какому другому событию) ты устанавливаешь некий флаг член класса m_bMyKeyDown = TRUE, тогда:

Код: (C++)
        MSG msg;
        m_bMyKeyDown = FALSE; // сбрасываем флаг
        while( !m_bMyKeyDown )
        {
                // тело цикла
                // ...


               // чуть не забыл - может потребуется дать команду обновить окошко
               UpdateWindow();
                // трюк!!! - даём возможность обработать накопившиеся сообщения
                while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) AfxGetApp()->PumpMessage();
        }

2. Если требуется ну очень большая скорость отображения, то я бы сделал своё окошко, в котором бы отрисовывал данные. Но это ессно требует неких энергетических и временных затрат. Начни с CEdit.
« Последнее редактирование: 03-07-2012 09:47 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #13 : 03-07-2012 09:58 » 

Джон, спасибо!
 Да-да Да-да
Получилось на тестовой программе, с CEDIT том числе. Сейчас буду менять основную программу.
Извините, что не написала , что пишу visual c++ 6 и использую MFC.  Улыбаюсь
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #14 : 03-07-2012 10:04 » 

Спасибо скажешь, когда в отпуск отпустят. Ага
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #15 : 06-07-2012 05:55 » 

К сожалению, в боевой программе ничего не получается.
Этот бесконечный цикл поставила в OnInitDialog и результата на экране нет. Чуствую смутно не туда  А черт его знает...
Если сделать конечное количество циклов, то информация на экране появляется по окончании всех циклов.
В общем караул! Жаль

Вад, бесконечное кол-во выводов на экран нужно для того , чтобы комиссия приёмки могла посмотреть на результаты работы их блока.
Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 06-07-2012 05:58 » 

В данном случае нужно показать и цикл и вывод
Кто, где и как
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
ann_nef
Помогающий

ru
Offline Offline
Пол: Женский

« Ответ #17 : 06-07-2012 06:08 » 

Сейчас кусок этот выделю, а то вся программа очень большая.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 06-07-2012 06:10 » 

ann_nef, если ты занимаешь основной поток приложения, то диалоги не могут быть обработаны: сообщения окон копятся в очереди, а обрабатывать их никто не может. По этому надо либо перенести твой бесконечный цикл в отдельный поток, либо делать конечный автомат, срабатывающий по событиям от COM-порта.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Гость
« Ответ #19 : 06-07-2012 07:23 » 

Или в каждой итерации цикла обрабатывать очередь сообщений TranslateMessage, DispatchMessage
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #20 : 06-07-2012 07:57 » 

К сожалению, в боевой программе ничего не получается.

Я думаю ты просто в торопях что-то упустила. Посмотри ещё раз всё внимательно. С UpdateWindow пробовала?

СТОП!!! только сейчас заметил ключевую фразу: "Этот бесконечный цикл поставила в OnInitDialog". Чесслово я бы удивился, если бы ТАК работало. Ага Само название Init уже подразумевает отсутствие каких либо иных действий, кроме инициаллизации.

Значит так. Быстренько добавляешь таймер на 100-250 мс, и запускаешь его в OnInitDialog. А уже по таймеру вызываешь ф-ю с циклом. Таймер ессно тут же убиваешь.

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

Ром, для этого и существует трюк, который я привёл. Всё прекрасно работает.
« Последнее редактирование: 06-07-2012 08:03 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 06-07-2012 08:34 » 

Значит так. Быстренько добавляешь таймер на 100-250 мс, и запускаешь его в OnInitDialog. А уже по таймеру вызываешь ф-ю с циклом. Таймер ессно тут же убиваешь.
Кстати, а просто в обработчике какого-нибудь WM_CREATE это можно сделать?
Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #22 : 06-07-2012 08:37 » 

А нельзя это цикл вынести куда-то отдельным потоком (процессом)?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
zubr
Гость
« Ответ #23 : 06-07-2012 09:11 » 

Цитата
начит так. Быстренько добавляешь таймер на 100-250 мс, и запускаешь его в OnInitDialog. А уже по таймеру вызываешь ф-ю с циклом. Таймер ессно тут же убиваешь.
Так не будет работать. Приложение все равно зависнет, так как не будет получать очередь сообщенией, чудес не бывает.
Будет работать, если итерацию цикла выполнять по таймеру.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #24 : 06-07-2012 09:18 » 

Кстати, а просто в обработчике какого-нибудь WM_CREATE это можно сделать?

Всё-равно мы говорим о моменте создания окна, а процесс наблюдения должен происходить уже после того как окно создано. Ведь процесс создания окна может быть прерван, по той или иной причине. Поэтому в данном случае таймер - простое и надёжное средство "развязки".

А нельзя это цикл вынести куда-то отдельным потоком (процессом)?

Слав, в принципе можно, но только всё-равно этот поток (процесс) должет отслеживать готовность (в данном случае - завершение создания) окна, или же запускаться после создания. Хрен редьки не слаще. Ибо нет смысла пытаться показать информацию в окне, которое ещё не создано, и/или контролы которого ещё не созданы.

Добавлено через 3 минуты и 56 секунд:
Так не будет работать. Приложение все равно зависнет, так как не будет получать очередь сообщенией, чудес не бывает.
Будет работать, если итерацию цикла выполнять по таймеру.

Как это? Почему? Я ж это не от фонаря написал. Я использовал это уже много раз в своих проектах. Всё прекрасно работает. Это стандартная нормальная асинхронная развязка. При создании окна (в данном случае при инициаллизации) запускается таймер. Сообщение таймера придёт после. По таймеру запускается ф-я с бесконечным (или с конечным) циклом. Какие проблемы? Зачем выполнять итерации цикла по таймеру?
« Последнее редактирование: 06-07-2012 09:22 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 06-07-2012 09:25 » 

готовность (в данном случае - завершение создания) окна
должен осуществлять модуль вывода

один "поток" читает буфера
второй - выводит
Третий занимается строительством "окон" и основой цикл.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #26 : 06-07-2012 09:37 » 

Слав, а зачем так сложно? Что значит модуль ввода? Есть приложение типа диалог, в этом диалоге должна отображаться опрашиваемая в цикле информация. Она должна отображаться в окне, те после его создания. Два потока для чтения/отображения необходимы, как я уже говорил выше, для большого количества данных и быстрой скорости отображения. Я такую штуку делал для сканеров, они там выплёвывают данных мегабайтов 5 в сек. Вот тогда да. FIFO буфер, свой контрол отображения. В данном случае это будет из "Бука" по комарам.
« Последнее редактирование: 06-07-2012 09:48 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
zubr
Гость
« Ответ #27 : 06-07-2012 09:51 » 

Цитата
Как это? Почему? Я ж это не от фонаря написал. Я использовал это уже много раз в своих проектах. Всё прекрасно работает. Это стандартная нормальная асинхронная развязка. При создании окна (в данном случае при инициаллизации) запускается таймер. Сообщение таймера придёт после. По таймеру запускается ф-я с бесконечным (или с конечным) циклом. Какие проблемы? Зачем выполнять итерации цикла по таймеру?
Джон, ты уверен? Я попробовал у себя так сделать, правда в дельфях, но не вижу разницы. Сделал таймер, который включается через 10 сек, а в обработчике таймера его отключаю и запускаю бесконечный цикл. Таймер устанавливаю в обработчике OnCreate формы. Приложение запускается, в течение этих 10 сек отвечает на действия пользователя, после чего закономерно зависает.
Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #28 : 06-07-2012 09:54 » 

1. Мы не знаем количества данных (начальный топик не показатель)
2. Не увидел "Бука" Разделение задач (потоков) где ж там "Бука"?

Работа по таймеру - можно только в качестве проверки "концепции" работоспособности.


кстати

Цикл чтения буферов
  тело цикла
  UpdateWindow();
...
причем "Цикл чтения буферов" это условно, не надо
Т.е. бесконечный цикл ожидания нажатия
чтение буферов, можно проводить не постоянно, а только, например каждые nnn мсек (проверять это в процедуре чтения)
соответственно настраивать и вывод
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #29 : 06-07-2012 10:02 » 

zubr, уверен Улыбаюсь. "Я не знаю как у Вас там в Стамбуле (Дельфях)" почти (с), но в С++ сделаю пример. Только не сейчас. Коропоратив - святое дело. Ага Я ща дома, через минут 10 выдвигаемся, как только семья будет готова, потом я в бюро заскочу, если будет время - сделаю, если нет, то завтра или в ближайшем будущем. Ага


Приложение запускается, в течение этих 10 сек отвечает на действия пользователя, после чего закономерно зависает.

А вот это ты делал?

Или в каждой итерации цикла обрабатывать очередь сообщений TranslateMessage, DispatchMessage

Насколько я понял, это древнегреческий эквивалент "моему" трюку.

Слав,

1. Почему не показатель? Это поставленная задача - 512 байтов.
2. Все уже вроде решилось и в тестовом проекте работает как надо. Насколько я понял, проблема теперь в рабочей проге. Так и эта проблема решается 5 строчками кода.



Добавлено через 2 часа, 1 минуту и 45 секунд:
Как говорят у нас  Ага : "bitteschön"


Код: (C++)
BOOL CTestUpdateDlgDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        SetIcon(m_hIcon, TRUE);
        SetIcon(m_hIcon, FALSE);

        SetTimer(MY_TIMER, 50, NULL);

        return TRUE;
}

void CTestUpdateDlgDlg::OnBnClickedOk()
{
        m_bMyStop = !m_bMyStop;

        if(!m_bMyStop)
        {
                SetTimer(MY_TIMER, 50, NULL);
        }
}

void CTestUpdateDlgDlg::OnTimer(UINT nIDEvent)
{
        if(MY_TIMER == nIDEvent)
        {
                KillTimer(MY_TIMER);
                GetDlgItem(IDOK)->SetWindowText(_T("Stop"));
                RunLoop();
        }
        CDialog::OnTimer(nIDEvent);
}

void CTestUpdateDlgDlg::RunLoop()
{
        MSG msg;
        m_bMyStop = FALSE;
        int i=0;
        while( !m_bMyStop )
        {
                CString stBuf;
                stBuf.Format(_T("%d"), i++);
                GetDlgItem(IDC_EDIT1)->SetWindowText(stBuf);
                if(i>100) i=0;
                while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) AfxGetApp()->PumpMessage();
        }
        GetDlgItem(IDOK)->SetWindowText(_T("Start"));
}

* TestUpdateDlg_exe.zip (80.41 Кб - загружено 981 раз.)
* TestUpdateDlg_src.zip (20.19 Кб - загружено 997 раз.)
« Последнее редактирование: 06-07-2012 12:09 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines