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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TThread + WaitForMultipleObjects, ожидание окончания потоков не происходит 
:(
    Опции темы
Dom
Дата 6.11.2009, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Столкнулся с тем что не могу понять как работает WaitForMultipleObjects. А может дело и не в нем.

Есть такой пример, большая часть кода позаимствована здесь smile

Код

unit Unit1;

interface

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

type
  TForm34 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

  TMy2Thread = class(TThread)
  private
    procedure Show1;
    procedure Show2;
  protected
    procedure Execute; override;
  end;

var
  Form34: TForm34;
  A: Integer = 0;

implementation
{$R *.dfm}
{ TMyThread }

procedure TMyThread.Execute;
begin
  Sleep(50);
  InterlockedIncrement(A);
  Sleep(1000);
end;

procedure TForm34.btn1Click(Sender: TObject);
var
  Handles: array of THandle;
  I: Integer;
  WaitRes: Cardinal;
begin
  SetLastError(NO_ERROR);
  SetLength(Handles, 50);
  A := 0;
  for I := Low(Handles) to High(Handles) do
    with TMyThread.Create(True) do
    begin
      Handles[I] := Handle;
      FreeOnTerminate := True;
      Resume;
    end;
  WaitRes := WaitForMultipleObjects(Length(Handles),
    @Handles, True, INFINITE);
  if WaitRes = WAIT_OBJECT_0 then
    ShowMessage(IntToStr(A))
  else
    ShowMessage(SysErrorMessage(GetLastError));
end;

procedure TForm34.btn2Click(Sender: TObject);
begin
{ чтобы не застывала главная форма выношу все в отдельный поток }
  TMy2Thread.Create(false).FreeOnTerminate := true; 
end;

{ TMy2Thread }

procedure TMy2Thread.Execute;
var
  Handles: array [1..MAXIMUM_WAIT_OBJECTS] of THandle;
  I: Integer;
  WaitRes: Cardinal;
begin
  SetLastError(NO_ERROR);
  A := 0;
  for I := Low(Handles) to High(Handles) do
    with TMyThread.Create(True) do
    begin
      Handles[I] := Handle;
      FreeOnTerminate := True;
      Resume;
    end;
  WaitRes := WaitForMultipleObjects(High(Handles),
    @Handles, True, INFINITE);
  if WaitRes = WAIT_OBJECT_0 then
    Synchronize(Show1)
  else
    Synchronize(Show2);
end;

procedure TMy2Thread.Show1;
begin
  ShowMessage(IntToStr(A))
end;

procedure TMy2Thread.Show2;
begin
  ShowMessage(SysErrorMessage(GetLastError));
end;

end.

Так вот процедура btn2Click отрабатывает как и предполагается, а вот btn1Click выдает ошибку "Неверный дескриптор".
1) Почему не получается обработать массив хэндлов произвольного размера, т.е. фактически произвольно задавать число создаваемых потоков?
2) Если после нажатия на btn2, пока не успели завершится все потоки, нажать на btn1, то выводимое значение А будет 50, т.е. отрабатывают только 50 потоков. Т.е. получается, что массивы Handles хоть и объявляются в каждой процедуре локально, но взаимосвязаны? Почему так? Пробовал переименовывать эти массивы, результат тот же.

Чувствую что истина где-то рядом... Помогите пожалуйста. smile
PM MAIL   Вверх
CodeMonkey
Дата 6.11.2009, 16:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 38
Всего: 89



Чему, по-вашему, равно @Handles для динамического массива?


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Демо
Дата 6.11.2009, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Если хочешь использовать функции WaitFor..., то FreeOnTerminate := False. Только не забывай для своих классов-потоков выполнять Free;


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


Эксперт
***


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

Репутация: 38
Всего: 89



Цитата(Демо @  6.11.2009,  22:29 Найти цитируемый пост)
Если хочешь использовать функции WaitFor..., то FreeOnTerminate := False.

Кста, ссылка в тему (у вас WaitFor = использование, завершение потока = закрытие).

(Демо, это не вам, а автору вопроса)


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Dom
Дата 6.11.2009, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



CodeMonkey, спасибо за ссылки!
С хэндлами, точнее с динамическим массивом разобрался. А вот с WaitFor это уже на свежую голову...
Только почему же в оригинальном примере FreeOnTerminate := True
Ладно, это уже завтра.
PM MAIL   Вверх
Dom
Дата 7.11.2009, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Так вот, возвращаясь к напечатанному. По поводу WaitFor...
FreeOnTerminate := False надо ставить, чтобы просто наверняка исключить ситуацию, когда поток завершится раньше вызова WaitFor... или с какой-то иной целью?
PM MAIL   Вверх
Демо
Дата 8.11.2009, 04:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dom @  7.11.2009,  15:25 Найти цитируемый пост)
Так вот, возвращаясь к напечатанному. По поводу WaitFor...
FreeOnTerminate := False надо ставить, чтобы просто наверняка исключить ситуацию, когда поток завершится раньше вызова WaitFor... или с какой-то иной целью?


С FreeOnTerminate=True ситуация следующая:

При завершении поточной поточной функции в основном потоке немедленно происходит освобождение TThread. 
Причём происходит оно раньше, чем начинает выполняться WaitFor.

Поэтому при ожидании завершения выполнения поточной функции нужно обязательно ставить FreeOnTerminate=False.


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


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



PM MAIL   Вверх
Dom
Дата 9.11.2009, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Спасибо всем за помощь!
Собрал еще одну тестовую программку. Работает как и задумывалось, что не может не радовать. Можно сказать основы усвоил. Теперь дело за малым - переписать старую прогу под многопоточность.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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