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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Повторное использование потока, TThread 
V
    Опции темы
NewDima
Дата 7.5.2009, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



Наследую обычный TThread. В общем не важно, что пишу в execute. Один раз вызываю resume, и поток нормально отрабатывает, никаких поблем. Вызываю после отработки второй раз - в execute не попадаю. Что за дела, кто знает?

Это сообщение отредактировал(а) NewDima - 7.5.2009, 16:25
PM ICQ   Вверх
Демо
Дата 7.5.2009, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



Цитата(NewDima @  7.5.2009,  16:22 Найти цитируемый пост)
th.Resume;
f := th.WaitFor;


Вот это как понимать?
После Resume th заканчивает свою работу?

Добавлено через 34 секунды
Приведи реализацию TThread.


--------------------
    
PM MAIL ICQ Skype   Вверх
NewDima
Дата 7.5.2009, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



собственно там ерунду написал, быстро сообразил и отредактировал, потому как к делу отношения не имеет =)
Код

TNewThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure sm;
    procedure Execute; override;
  end;
...
procedure TNewThread.sm;
begin
ShowMessage('dwad');
end;

procedure TNewThread.Execute;
begin
Synchronize(sm);
  { Place thread code here }
end;

Не хитро, правда? В общем по стандарту решил проверить, потому как заметил на своем другом потоке
PM ICQ   Вверх
Демо
Дата 7.5.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



Цитата(NewDima @  7.5.2009,  16:29 Найти цитируемый пост)
Не хитро, правда? В общем по стандарту решил проверить, потому как заметил на своем другом потоке 


Категорически выбрось такие "Стандарты". Видимо, это стандарт Флёнова.

Метод Execute выполняется в отдельном потоке(нити). После того, как этот метод закончился, дополнительный поток терминируется, и ни о каком повторном использовании речи быть не может.

 
Цитата(NewDima @  7.5.2009,  16:29 Найти цитируемый пост)
procedure TNewThread.Execute;
begin
Synchronize(sm);
  { Place thread code here }
end;


Используя таким способом Synchronize, ты выполняешь TNewThread.sm в основном потоке.

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

Это сообщение отредактировал(а) Демо - 7.5.2009, 16:36


--------------------
    
PM MAIL ICQ Skype   Вверх
NewDima
Дата 7.5.2009, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



Цитата(Демо @ 7.5.2009,  23:35)
Используя таким способом Synchronize, ты выполняешь TNewThread.sm в основном потоке.

не понял, это с каких пор? я перекрываю виртуальный execute и ресумом перевожу поток в состояние готовности для шедуллера винды. Я так полагаю, под словом терминируется вы имели ввиду "освобождается"? ан нет, я не устанавливал FreeOnTerminate  в true
PM ICQ   Вверх
kami
Дата 7.5.2009, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(NewDima @  7.5.2009,  16:43 Найти цитируемый пост)
под словом терминируется вы имели ввиду "освобождается"

Не нужно путать виндовые потоки и класс-обертку TThread.
Когда происходит выход из Execute TThread виндовый поток завершается. Винда про него забывает. Все - для нее этого потока больше не существует.
А вот экземпляр класса остается. Но вот сделать он с потоком больше ничего не может. Потому что нет больше этого потока. Цирк уехал, а клоуны остались. В смысле - поток завершен и выброшен на свалку истории, а экземпляр TThread, его методы и свойства остаются доступными для вычисления последствий отработки потока.


Цитата(NewDima @  7.5.2009,  16:43 Найти цитируемый пост)
не понял, это с каких пор?

С самых обычных.
Если в методе Execute есть только  Synchronize, то само наличие дополнительного потока теряет смысл и только усложняет архитектуру приложения.

Добавлено через 6 минут и 7 секунд
Цитата(Демо @  7.5.2009,  16:35 Найти цитируемый пост)
Видимо, это стандарт Флёнова.

+100 !!!
PM MAIL WWW   Вверх
Демо
Дата 7.5.2009, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



Обещанный пример:

Код

unit uRetrThr;

interface

uses
  Windows, Classes;

type

  TRetrThr=class(TThread)
  private
    FSignalJob: THandle;
    FSignalThr: THandle;
    FParam: String;
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;

    function Start(const Value: String;
      WaitStarting: Boolean=True): Boolean;
  end;

implementation


{ TRetrThr }

constructor TRetrThr.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FSignalJob := CreateEvent(nil,False,False,'');
  FSignalThr := CreateEvent(nil,False,False,'');
  Resume;
  SetEvent(FSignalThr);
end;

destructor TRetrThr.Destroy;
begin
  CloseHandle(FSignalJob);
  CloseHandle(FSignalThr);
  inherited;
end;

procedure TRetrThr.Execute;
begin
  repeat
    WaitForSingleObject(FSignalJob,Infinite);
    Sleep(3000);
    SetEvent(FSignalThr);
  until Terminated;
end;

function TRetrThr.Start(const Value: String;
  WaitStarting: Boolean=True): Boolean;
var
  RC: Cardinal;
begin
  RC := 1;

  case WaitStarting of
    True: RC := WaitForSingleObject(FSignalThr,INFINITE);
    False: RC := WaitForSingleObject(FSignalThr,0);
  end;

  Result := RC=WAIT_OBJECT_0;
  if not Result then Exit;

  FParam := Value;
  SetEvent(FSignalJob);
end;

end.


Код

unit ufMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, uRetrThr;

type

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  RH: TRetrThr;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  if not RH.Start('Âûçîâ',False) then ShowMEssage('Îøèáêà');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  RH := TRetrThr.Create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  RH.Terminate;
end;

end.




--------------------
    
PM MAIL ICQ Skype   Вверх
NewDima
Дата 8.5.2009, 03:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



Причем стандарты Фленова? Стандартный делфийский поток создаю, собственно в его каркас вставляю код. А то что в экзэкьюте используется только один метод, вызываемый Synchronize не значит, что я использую его вообще. Настоящий поток устроен совсем по-другому, а этот писал для проверки, дохнет ли виндовская нить при выходе из экзекьюта. Я полагал, что при выходе она впадает в состояние приостановки, в этом и ошибся.
А по архитектуре приложения, то мне нужен класс, которому устанавливаешь задание и запускаешь, причем во время работы его можно было корректно приостановить (не саспендом в моем случае), а потом продолжить работу далее. А по выполнению задания он должен останавливаться. Это я реализовал, только проще, и только уже утром, когда проспался. Всем удачи
PS кстати, о Фленове, даже не подозреваю, кто это, если пишет книги, то я ни одной книги не прочитал, только мсдн

Это сообщение отредактировал(а) NewDima - 8.5.2009, 03:51
PM ICQ   Вверх
Демо
Дата 8.5.2009, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



Цитата(NewDima @  8.5.2009,  03:51 Найти цитируемый пост)
Это я реализовал, только проще, и только уже утром, когда проспался.


Ну так поделился бы своим решением.


--------------------
    
PM MAIL ICQ Skype   Вверх
NewDima
Дата 8.5.2009, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



Код

type
  TDownloadThread = class (TThread)
    private
      FForPause: boolean;
      FConnection: HINTERNET;
      FConnected: boolean;
      FFileName: string;
      FError: integer;

      FSheduled: boolean;
      FSheduleURL: string;
      FSheduleStart: integer;
      FSheduleLen: integer;
      FSheduleError: integer;

      FOnDownloaded: TNotifyEvent;
    protected
      procedure Execute(); override;
      procedure Connect();
      procedure DoLoaded();
      function  ReadPeace(): integer;
    public
      property    Connected: boolean read FConnected;
      property    ErrorCode: integer read FError;
      property    OnDownloaded: TNotifyEvent read FOnDownloaded write FOnDownloaded;
      constructor Create(AFileName: string);
      destructor  Destroy();
      function    Download(Url: string; Start, Len: integer): integer;
      function    DownloadAgain(): integer;
      procedure   PauseDownloading();
    published
  end;

implementation

constructor TDownloadThread.Create(AFileName: string);
begin
inherited Create(true);
...
Connect();
end;

destructor TDownloadThread.Destroy;
begin
...
inherited;
end;

procedure TDownloadThread.DoLoaded();
begin
FOnDownloaded(self);
End;

procedure TDownloadThread.Connect();
begin
...
end;

procedure TDownloadThread.Execute;
begin
repeat
ReadPeace();
if (FSheduleLen <= 0) or (not FForPause) then
  FSheduled := false;
FError := FSheduleError;
if (FSheduleLen<=0) and (Assigned(FOnDownloaded)) then
  Synchronize(DoLoaded);
Suspend;
until Terminated;
end;

function TDownloadThread.Download(Url: string; Start, Len: integer): integer;
begin
if FSheduled then exit;
FSheduled := true;
FSheduleStart := Start;
FSheduleLen := Len;
FSheduleURL := Url;
Resume;
end;

function TDownloadThread.DownloadAgain(): integer;
begin
if not FSheduled then exit;
FForPause := false;
Resume();
end;

procedure TDownloadThread.PauseDownloading;
begin
FForPause := true;
end;

function TDownloadThread.ReadPeace(): integer;
begin
...
end;
end.


PM ICQ   Вверх
Демо
Дата 8.5.2009, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 3.11.2005

Репутация: 30
Всего: 50



NewDima, 
Не хочу сказать ничего плохого, но алгоритм крайне ненадёжен.
Возможны одновременные успешные попытки выполнения TDownloadThread.Download.


--------------------
    
PM MAIL ICQ Skype   Вверх
MetalFan
Дата 8.5.2009, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



вообще не очень хорошо использовать suspend-resume...


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
NewDima
Дата 9.5.2009, 05:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



MetalFan, хотелось бы увидеть аргументы, хотя я и сам так подумываю, но все-таки =)
PM ICQ   Вверх
Alexeis
Дата 9.5.2009, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



Цитата(NewDima @  9.5.2009,  04:16 Найти цитируемый пост)
хотелось бы увидеть аргументы

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


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

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

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: 2
Всего: 12



дело в том, что suspend и resume вызываются только в самом классе, причем в соответствующих случаях закрываются(или открываются) нужные дескрипторы. Разве это не должный контроль ресурсов?

Добавлено через 14 минут и 17 секунд
Демо, ты имеешь ввиду, что два других потока попытаются выполнить этот метод? Если честно, не совсем понимаю, почему такое возможно
PM ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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