• 0
DMS

Еще раз о потоках

Вопросы

Господа, подскажите, как вызвать друг за другом три процедуры с потоками внутри, но так - чтобы вызов каждой процедуры (начиная со второй) зависел от результатов предыдущей процедуры?

Поясняю примером:

procedure TForm1.Button1Click(Sender: TObject);
begin
  FirstThread;
  SecondThread;
  ThirdThread;
end;

procedure TForm1.FirstThread;
var
  I: Integer;
begin
  Memo1.Lines.Add('First Begin: ' + TimeToStr(Now));
  I := 0;

  TTask.Run(
    procedure
    begin
      while (I < 300000000) do
        Inc(I);

      TThread.Synchronize(TThread.CurrentThread,
        procedure
        begin
          Memo1.Lines.Add('First Thread: ' + TimeToStr(Now));
        end)
    end);

  Memo1.Lines.Add('First End: ' + TimeToStr(Now));
end;

procedure TForm1.SecondThread;
var
  I: Integer;
begin
  Memo1.Lines.Add('Second Begin: ' + TimeToStr(Now));
  I := 0;

  TTask.Run(
    procedure
    begin
      while (I < 800000000) do
        Inc(I);

      TThread.Synchronize(TThread.CurrentThread,
        procedure
        begin
          Memo1.Lines.Add('Second Thread: ' + TimeToStr(Now));
        end)
    end);

  Memo1.Lines.Add('Second End: ' + TimeToStr(Now));
end;

procedure TForm1.ThirdThread;
var
  I: Integer;
begin
  Memo1.Lines.Add('Third Begin: ' + TimeToStr(Now));
  I := 0;

  TTask.Run(
    procedure
    begin
      while (I < 900000000) do
        Inc(I);

      TThread.Synchronize(TThread.CurrentThread,
        procedure
        begin
          Memo1.Lines.Add('Third Thread: ' + TimeToStr(Now));
        end)
    end);

  Memo1.Lines.Add('Third End: ' + TimeToStr(Now));
end;

В Memo попадают сначала "Begin End" и только потом - First Thread, Second Thread, Third Thread.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 ответов на этот вопрос

  • 0
2 часа назад, DMS сказал:

В Memo попадают сначала "Begin End" и только потом - First Thread, Second Thread, Third Thread.

все правильно попадают. Вы же сами делаете TTask.Run, который создает доп. поток. То есть, последовательность выполнения каждого XXXThread получается следующая:
1. вывести Begin
2. запустить Task, который выполнится когда-нибудь.
3. вывести end.

когда все 3 пункта выполнились - стартуют внутренности TTask, которые выводят надпись Thread.

2 часа назад, DMS сказал:

чтобы вызов каждой процедуры (начиная со второй) зависел от результатов предыдущей процедуры?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Я не спорю, что всё правильно Delphi делает. Я просто хочу спросить совета, как сделать так, чтобы и потоки были (против зависания), и можно было управлять их запуском. Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 час назад, DMS сказал:

ак сделать так, чтобы и потоки были (против зависания), и можно было управлять их запуском.

собственно, совет уже был дан: весь код запихать в 1 поток. Перед выполнением каждого следующего действия - проверять, а не прервали ли поток (if Terminated then exit). Не забывая высвобождать задействованные ресурсы.
Если же действия все-таки можно распараллелить (к примеру: есть огромный массив данных, над которым нужно выполнить x действий. Тогда делаем в одном потоке 1-е действие над y записями - отдаем второму потоку, а сами продолжаем обрабатывать дальше. Второй поток обработал часть данных - передал дальше. Минимизируется непроизводительный простой) - тогда есть смысл посмотреть в сторону пайпов в OmniThreadLibrary

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Вместо TTask.Run можно использовать TThread.CreateAnonymousThread в связке с TThread.OnTerminate

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

А что мешает дождаться завершения потока и по его результату запускать следующий?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
22 часа назад, GASCHE сказал:

А что мешает дождаться завершения потока и по его результату запускать следующий?

Поток вызванный в синхронизации другого потока?)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
24 минуты назад, Равиль Зарипов (ZuBy) сказал:

Поток вызванный в синхронизации другого потока?)

Так тоже интересно попробовать, но я имел ввиду WaitForAny или

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
12 часа назад, GASCHE сказал:

но я имел ввиду WaitForAny

В данном случае это всё избыточно и непроизводительно. Увеличивает сложность приложения без получения профита. Наоборот, производительность будет хуже. Особенно - на нагруженной системе.
С учетом условия

В 17.02.2018 в 13:20, DMS сказал:

вызвать друг за другом три процедуры

это всё надо делать в одном потоке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
2 часа назад, kami сказал:

С учетом условия это всё надо делать в одном потоке.

Да я согласен, но не ясно

В 17.02.2018 в 13:20, DMS сказал:

чтобы вызов каждой процедуры (начиная со второй) зависел от результатов предыдущей процедуры?

...

и можно было управлять их запуском

что автор имел ввиду под словами 'зависел и управлять', тут возможны разные толкования.

 

 

 

Изменено пользователем GASCHE

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
23 минуты назад, GASCHE сказал:

Да я согласен, но не ясно

что автор имел ввиду под словами 'зависел и управлять', тут возможны разные толкования.

 

 

 

Под "зависел" имелось в виду, запускать ли следующую процедуру или нет (в зависимости от результатов предыдущей процедуры)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
14 минуты назад, DMS сказал:

Под "зависел" имелось в виду, запускать ли следующую процедуру или нет

Кто должен принимать решение программа или оператор?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу