Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 20.09.2012, 08:45
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию Публичные свойства у потоков

Допустим есть некий поток:
Код:
unit MVCThread;

interface

uses
  Classes;

type
  TMVCCreateStruct = record
    port:string;
    baudrate:Integer;

  end;
  TMVCThread = class(TThread)
  private
    FSomeProp: Boolean;
    procedure SyncProc;
  protected
    procedure Execute; override;
  public
    property SomeProp:Boolean read FSomeProp write FSomeProp;
  end;

implementation

{ 
  Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);  

  and UpdateCaption could look like,

    procedure TMVCThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; 
    
    or 
    
    Synchronize( 
      procedure 
      begin
        Form1.Caption := 'Updated in thread via an anonymous method' 
      end
      )
    );
    
  where an anonymous method is passed.

  Similarly, the developer can call the Queue method with similar parameters as
  above, instead passing another TThread class as the first parameter, putting
  the calling thread in a queue with the other thread.

}

{ TMVCThread }

procedure TMVCThread.Execute;
begin
  { Place thread code here }
  while not Terminated do
    begin
      Sleep(100);
      if FSomeProp then
        Synchronize(SyncProc);
    end;
end;

procedure TMVCThread.SyncProc;
begin
  //код
end;

end.
Свойство SomeProp буду устанавливать из основного потока приложения. Вопрос: насколько это безопасно, и правильно ли вообще так писать?
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #2  
Старый 20.09.2012, 09:02
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Aristarh Dark
Свойство SomeProp буду устанавливать из основного потока приложения. Вопрос: насколько это безопасно, и правильно ли вообще так писать?
Это не безопасно. Нужно каким либо образом сообщить потоку о своём намерении, и когда он станет в ожидание, можно изменять свойство. Ну и после этого главное не забыть опять запустить поток
Ответить с цитированием
  #3  
Старый 20.09.2012, 09:14
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

можно через модификатор, устанавливать флаг, в цике казнения смотреть на этот флаг и только в том случае, если он установлен - менять значение переменной.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #4  
Старый 20.09.2012, 09:25
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Однако подобное свойство есть.
Например: FOnTerminate.
Причем если там посмотреть вызовы, то проверки выполняются в каждой процедуре (вызовы одна из другой, смотрите исходники TThread), следовательно теоретически возможно изменение свойства между вызовами.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #5  
Старый 20.09.2012, 10:12
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

для скалярного Boolean сгодится и так. посмотри на свойство Terminated и метод Terminate у TThread:

Код:
TThread = class
private
  FTerminated: Boolean;
protected
  property Terminated: Boolean read FTerminated;
public
  procedure Terminate;

procedure TThread.Terminate;
begin
  FTerminated := True;
end;

вполне естественно вызывать из основного потока методы Terminate и WaitFor для завершения и ожидания работы потока, когда в самом потоке может быть проверка Terminated, как в первом посте.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #6  
Старый 20.09.2012, 10:15
Аватар для ~TB~
~TB~ ~TB~ вне форума
Начинающий
 
Регистрация: 17.02.2006
Адрес: Казахстан
Сообщения: 172
Версия Delphi: XE
Репутация: 1500
По умолчанию

У меня в одном приложении примерно так работает. Проблем никаких не наблюдаю. Главное не забывать пинать поток когда нужно.

Код:
procedure TMySuperDuperThread.Execute;
begin
  while not Terminated do
    if not Suspended then
    begin
      if SomeProp then
        ApplySomeProcedure
      else
        Suspend;
    end;
end;
__________________
00110001 00101100 00110110 00110001 00111000 00110000 00110011 00110011 00111001 00111000 00111000 00110111 00110100 00111001 00111000 00111001 00110100 00111000 00110100 00111000 00110010 00110000 00110100 00110101 00111000 00110110 00111000 00110011 00110100 00110011 00110110 00110101 00110110
Ответить с цитированием
  #7  
Старый 20.09.2012, 10:22
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

И самое главное, нафига внутри Execute вся полезная работа делается под Synchronize ?
Ответить с цитированием
  #8  
Старый 20.09.2012, 10:23
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Цитата:
Сообщение от ~TB~
У меня
для "тяжелых" случаев есть целый раздел "Synchronization Functions"
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #9  
Старый 20.09.2012, 10:28
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Aristarh Dark
Однако подобное свойство есть.
Например: FOnTerminate.
Причем если там посмотреть вызовы, то проверки выполняются в каждой процедуре (вызовы одна из другой, смотрите исходники TThread), следовательно теоретически возможно изменение свойства между вызовами.
Свойство OnTerminate основной поток изменяет только после создания потока и до его запуска:
Код:
  Thread := TMyThread.Create(True);
  Thread.OnTerminate := MyMethod; // Здесь спокойно можно присваивать
  Thread.Resume;
  Thread.OnTerminate := MyMethod; // А вот здесь уже нельзя

Цитата:
Сообщение от NumLock
вполне естественно вызывать из основного потока методы Terminate и WaitFor для завершения и ожидания работы потока, когда в самом потоке может быть проверка Terminated, как в первом посте.
Изменение свойства может произойти посреди какой нибудь проверки, в результате чего может нарушиться логика работы.
Для Terminated это не страшно, так как единственное его предназначение это:
Код:
while not Terminated do
begin
...
  if Terminated then Break; // Это тоже не повлияет на логику
...
end;
Ответить с цитированием
  #10  
Старый 20.09.2012, 11:05
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от ~TB~
У меня в одном приложении примерно так работает. Проблем никаких не наблюдаю. Главное не забывать пинать поток когда нужно.

Код:
procedure TMySuperDuperThread.Execute;
begin
  while not Terminated do
    if not Suspended then
    begin
      if SomeProp then
        ApplySomeProcedure
      else
        Suspend;
    end;
end;
А разве проверка "if not Suspended then" здесь нужна и имеет смысл? Если поток остановлен, то он никак не может проверить своё состояние, а если поток запущен, то это условие всегда будет давать Истину.

Цитата:
Сообщение от icWasya
И самое главное, нафига внутри Execute вся полезная работа делается под Synchronize ?
Я так понял, что в том примере под полезной работой подразумевается это:
Код:
Sleep(100);
А свойство SomeProp нужно, чтобы основной поток мог сигнализировать этому потоку, что нужны результаты его работы.
Ответить с цитированием
  #11  
Старый 20.09.2012, 11:14
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

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

добавлено позже
пока отвлекся на работу и писал сообщение пример уже описали)))

добавлено еще позже
вариант ~TB~ мне тоже не понятен
__________________
Пишу программы за еду.
__________________

Последний раз редактировалось NumLock, 20.09.2012 в 11:17.
Ответить с цитированием
  #12  
Старый 20.09.2012, 11:29
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Цитата:
Сообщение от icWasya
И самое главное, нафига внутри Execute вся полезная работа делается под Synchronize ?


Код приведен для примера, если очень интересно согу выложить, то что получится в итоге. Объект сейчас в разработке.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #13  
Старый 20.09.2012, 15:59
Аватар для ~TB~
~TB~ ~TB~ вне форума
Начинающий
 
Регистрация: 17.02.2006
Адрес: Казахстан
Сообщения: 172
Версия Delphi: XE
Репутация: 1500
По умолчанию

NumLock, poli-smen,
Код:
if not Suspended then
Эээ... я не знаю зачем я это написал О_о
Правда - только что обратил внимание. Надо будет глянуть этот исходник и посмотреть что там делается. Скорее всего это какие-нибудь остатки совсем старого кода.
__________________
00110001 00101100 00110110 00110001 00111000 00110000 00110011 00110011 00111001 00111000 00111000 00110111 00110100 00111001 00111000 00111001 00110100 00111000 00110100 00111000 00110010 00110000 00110100 00110101 00111000 00110110 00111000 00110011 00110100 00110011 00110110 00110101 00110110
Ответить с цитированием
  #14  
Старый 20.09.2012, 16:14
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Как показала практика: свойство работает.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 07:47.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025