Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Снова о потоках и окне прогресса. 
:(
    Опции темы
JSinx
Дата 1.11.2008, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 12.12.2006

Репутация: нет
Всего: 1



Не могу понять как сделать правильно :(

Есть функция обработки данных, при обработке в окне прогресса должно показываться текущие состояние обработки, выводить различные сообщения (в memo). Так же есть 2 кнопки Пауза/Продолжить и Остановить.

Сделал я так.
В функции обработки данных вызывается метод, в который передается сообщение в лог (если нужно) и процент обработки.

Код

procedure ProcessData(var data : array of string)
begin
  for i := 0 to Length( data )-1 do
  begin
    ....
    tstThread.OnProcess( 'сообщение', i*100 / Length( data ) )
  end;  
end

tstThread = class( TThread )
private
 fLog : string;
 fPos : integer
// + объявления всех нужных методов
end;

tstThread.Execute;
begin
   ProcessData( данные );
end;

tstThread.OnProcess( logMsg : string; posit : integer );
begin
  fLog := logMsg;
  fPos := posit;
  Synhronize( ShowPosit );
end

tstThread.ShowPosit;
begin
  memo1.Lines.Add( fLog );
  posBar.Position := fPos;
end



Собственно вопросы:
1) Правильный ли у меня подход или нет?
2) При нажатии кнопки Пауза я делаю suspend, но у меня тогда и окно программы не прорисовывается :( соответственно не могу нажать кнопку продолжить. Что нужно сделать, чтобы приостановить поток, и потом продолжить его работу smile? (окно с прогрессБаром, логом и кнопками показано модально)



PM MAIL   Вверх
Alexeis
Дата 3.11.2008, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Так все вроде верно.
Цитата(JSinx @  1.11.2008,  15:03 Найти цитируемый пост)
При нажатии кнопки Пауза я делаю suspend
 Так зачем же усыплять главный поток? Или так происходит во время синхронизации? По мне лучше усыплять в строго заданные моменты. Например воспользоваться эвентом. Или отправить сообщение второму потоку мол остановись. Когда второй поток получит его, то в ответ пошлет сообщения "Я остановился" при помощи SendMessage. До тех пор пока главный поток не скажет что сообщение обработано второй уснет. Или главный займет критическую секцию, а второй заблокируется на входе в нее. Общий принцип таков.
1й поток: "2й замри"
1й поток: "Жду пока второй замрет"
2й поток: "Получил команду замри"
2й поток: "Завершаю основной цикл действий, Готовлюсь к переходу в режим ожидания"
2й поток: "1му я замер"
2й поток: "Заблокировался"
1й поток: "Дождался пока 2й уснет, продолжаю работу"


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
JSinx
Дата 9.11.2008, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 12.12.2006

Репутация: нет
Всего: 1



Цитата(Alexeis @ 3.11.2008,  11:07)
Так все вроде верно.

Общий принцип таков.
1й поток: "2й замри"
1й поток: "Жду пока второй замрет"
2й поток: "Получил команду замри"
2й поток: "Завершаю основной цикл действий, Готовлюсь к переходу в режим ожидания"
2й поток: "1му я замер"
2й поток: "Заблокировался"
1й поток: "Дождался пока 2й уснет, продолжаю работу"


Немного не понял, как сказать 2му замереть и подождать, может побольше документации надо почитать smile
Пока что я сделал так: добавил флаг пауза, и проверяю его в функции обработки данных, и если он установлен, то вызывается sleep().

Код

procedure ProcessData(var data : array of string)
begin
  for i := 0 to Length( data )-1 do
  begin
    while pause do sleep(100);
    ....
    tstThread.OnProcess( 'сообщение', i*100 / Length( data ) );
  end;  
end

При нажатии на кнопку "пауза" устанавливается в true этот флаг и трэду делается suspend. Правда, мне кажется, в таком случае нет смысла делать треду Suspend, т.к. и так впадаем в цикл, который ничего не делает.
Код

procedure btnPauseClick(Sender: TObject);
begin
  if Pause then
  begin
    btnPause.Caption := 'Пауза';
    tstThread.Resume;
  end
  else
  begin
    btnPause.Caption := 'Продолжить';
    tstThread.Suspend;
  end;
  Pause := not Pause;
end

P.S. Так же такой код работает, если при установке флага Pause, не "впадать" в цикл, а просто проверить условие:
Код

procedure ProcessData(var data : array of string)
begin
  for i := 0 to Length( data )-1 do
  begin
    if pause then sleep(100);
    ....
    tstThread.OnProcess( 'сообщение', i*100 / Length( data ) );
  end;  
end

Трэд тоже suspend'иться smile


PM MAIL   Вверх
Alexeis
Дата 10.11.2008, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(JSinx @  9.11.2008,  22:15 Найти цитируемый пост)
Немного не понял, как сказать 2му замереть и подождать, может побольше документации надо почитать smile

  Способов много. Поток замирает если ждет чего-то. Ждать он может 
1) освобождения ресурса эвент/семафор/мьютекс, если его занял другой поток
2) завершения работы другого потока.
3) обработки сообщения (если он отправил сообщение при помощи SendMessage).
4) освобождения критической секции, если в нее зашел другой поток.
5) ждать прихода любого сообщения (функция GetMessage).

Вариантов очень много почитайте эту тему http://forum.vingrad.ru/index.php?show_typ...showtopic=60076

Добавлено через 7 минут и 54 секунды
  Сказать чтобы он замер можно отправив сообщение или переключив Event второй поток узнав об этом должен опять же либо просигнализировать что он не занимается больше ни чем и готов заснуть, например установить тот же самый эвент в другое состояние. Если главный поток его ждал, то после переключения он продолжит свою работу. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0458 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.