Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4 5   вперед  Ctrl      все
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Dmitry Arefiev
Хорошо работающая PPL это благо для начинающих (и не только).
Либо заголовок не правильный, либо план учебника ...


Возможно в будущем появятся разделы, посвящённые PPL. Тем более PPL все активнее вторгается в нашу жизнь :) Но и помимо PPL есть много тем, которые хотелось бы описать (например, руки пока не дошли до описания темы синхронизации между потоками, а это, я считаю, очень важно). Но благодаря реализации функции ThreadWaitTimeout удаётся до последнего оттягивать такую сложную для понимания тему, как эвенты.
8 июл 20, 23:34    [22164470]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Dmitry Arefiev
DmSer
Оказывается ...

Так ты знаешь PPL или только TThread ? :)


Я изучал довольно много материала по PPL, смотрел видео-уроки, проводил некоторые эксперименты, так что считаю, что знаю о ней достаточно много.
8 июл 20, 23:37    [22164471]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4236
DmSer
X-Cite
procedure TForm1.Button2Click(Sender: TObject);
var
  x: ITask;
begin
  x := TTask.Run(
    procedure
    var
      a: TArray<Byte>;
    begin
      for var k := 1 to 3 do
      begin
        SetLength(a, 1024 * 1024 * 500);
        FillChar(a[0], 1024 * 1024 * 500, 5);
        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
          Exit;
        TFile.WriteAllBytes('C:\TTask.txt', a);
      end;
    end
  );
  while x.Status <> TTaskStatus.Running do
    ; // Убеждаемся что задача начала выполнятся
  x.Cancel();
  Application.Terminate();
end;

.


И тут блестящая PPL разом превратилась в тыкву! Оказывается, как и с TThread, нужно останавливать таски перед завершением программы, а в таске проверять необходимость завершения :)


Это еще не идёт речь о том, что часто потоки нужно завершать в определенном порядке. Как это сделать с тасками - объяснить начинающему программисту будет проблематично :)
9 июл 20, 00:32    [22164484]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Дегтярев Евгений
Member

Откуда: Барнаул
Сообщений: 1908
DmSer
(имею ввиду прежде всего GoLang) в сто раз меньше связанных с многопоточностью проблем и граблей, чем в языке Delphi. А теперь им еще и шедулер улучшили!

ты про шедулершедулер или gc?
9 июл 20, 06:17    [22164501]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Дегтярев Евгений
DmSer
(имею ввиду прежде всего GoLang) в сто раз меньше связанных с многопоточностью проблем и граблей, чем в языке Delphi. А теперь им еще и шедулер улучшили!

ты про шедулершедулер или gc?


Раньше кооперативный планировщик был, а работу планировщика ОС они грубо говоря игнорировали. Теперь учитывают.
9 июл 20, 08:50    [22164521]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1747
YuRock

Это еще не идёт речь о том, что часто потоки нужно завершать в определенном порядке. Как это сделать с тасками - объяснить начинающему программисту будет проблематично :)


Опять путаница между теплым и мягким.

Есть различные задачи, которые надо реализовать.
Эти все задачи можно и нужно отнести к определенным классам задач.
И здесь вступает в игру то, что для разных классов задач, подходят разные решения.

Если говорить о Delphi, то для класса задач асинхронного ожидания ответа или исполнения лучше подходят TTask.
Для класса задач распараллеливания лучше подходит TParallel.
Для класса задач фонового (долгого, постоянного, возможно на время жизни всего приложения) выполнения (То о чем тут чаще всего говорят) к сожалению нет никакого BackgroundService который бы умел и зависимости разруливать и шедулер иметь нормальный и прочее, но из того что есть лучше подходит как раз TThread.

На самом деле TThread - это класс для выполнения фоновых (долгоиграющих) задач.

Если говорить о теме топика, то я не понимаю что такое многопоточное программирование. Есть решение задач с помощью потоков - это уже звучит по другому. И как минимум понятно, что не все задачи можно и нужно решать с помощью потоков.

Сообщение было отредактировано: 9 июл 20, 10:37
9 июл 20, 10:38    [22164548]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Дегтярев Евгений
Member

Откуда: Барнаул
Сообщений: 1908
DmSer
Дегтярев Евгений
пропущено...
ты про шедулершедулер или gc?

Раньше кооперативный планировщик был, а работу планировщика ОС они грубо говоря игнорировали. Теперь учитывают.

видимо у авторов были веские причины запилить это, но как по мне оно решает настолько нетипичную для гошного кода ситуацию
9 июл 20, 20:03    [22164833]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 26714
У меня ощущение, что многие критикующие пропустили важные слова - "для начинающих".
10 июл 20, 00:16    [22164956]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6017
X-Cite
Если говорить о теме топика, то я не понимаю что такое многопоточное программирование. Есть решение задач с помощью потоков - это уже звучит по другому. И как минимум понятно, что не все задачи можно и нужно решать с помощью потоков.
Это умение "сшивать" взаимодействие потоков и знать как использовать различные способы синхронизации. А что-то там считать - ничем от однопоточного не отличается
10 июл 20, 08:32    [22164997]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6017
X-Cite
Проблема в Дельфи в том, что разработчики которые туда пытаются придти учатся по книжкам которые написаны были во времена высокого порога входа в программирование, а не когда курсы клепают по 100 "программистов" в день...

Поэтому лучше, чтобы появлялись книжки, которые позволят вчерашним студентам, которые не знают как там работает под капотом, да и не надо им знать, но которые будут эффективно решать реальные бизнес-задачи используя современные инструменты.

1. проблема в том, что такие "программисты" никому и не нужны - если они не чисто за корочкой идут
2. нету реальных бизнес-задач с потоками, которые могут решать "прошедшие курсы" :-)
10 июл 20, 08:38    [22165001]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Док
Member

Откуда: Казань
Сообщений: 6753
wadman
У меня ощущение, что многие критикующие пропустили важные слова - "для начинающих".

просто пиписьками меряются друг перед другом. Другого объяснения нет
10 июл 20, 09:03    [22165012]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Док
Member

Откуда: Казань
Сообщений: 6753
DmSer,
я не уверен, но может быть при ручном убиении потока кошернее делать экземпляру потока не просто Free, а Free + Nil?

Я обычно провожу проверку на существование предыдущего экземпляра прежде, чем запустить новый, типа:
type
Form1 = class(TForm)
...
private
FMyThread: TMyThread;
...
end;

procedure Button1Click...
begin
  //если сделать просто FMyThread.Free, то праздника не получится
  if Assigned(FMyThread) the Exit;
  ...
end;
10 июл 20, 09:16    [22165019]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Док
DmSer,
я не уверен, но может быть при ручном убиении потока кошернее делать экземпляру потока не просто Free, а Free + Nil?

Я обычно провожу проверку на существование предыдущего экземпляра прежде, чем запустить новый, типа:
type
Form1 = class(TForm)
...
private
FMyThread: TMyThread;
...
end;

procedure Button1Click...
begin
  //если сделать просто FMyThread.Free, то праздника не получится
  if Assigned(FMyThread) the Exit;
  ...
end;


Конечно, так и нужно. А в каком примере nil отсутствует? Вроде следил, чтобы везде было!
10 июл 20, 14:40    [22165302]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Док
Member

Откуда: Казань
Сообщений: 6753
DmSer
А в каком примере nil отсутствует?

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // При закрытии программы необходимо завершить работу потока
  // и уничтожить объект потока MyThread
  if MyThread <> nil then
    MyThread.Free;
end;

стр 16
10 июл 20, 14:48    [22165307]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Док
DmSer
А в каком примере nil отсутствует?

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // При закрытии программы необходимо завершить работу потока
  // и уничтожить объект потока MyThread
  if MyThread <> nil then
    MyThread.Free;
end;

стр 16


Здесь нормально, тут же FormDestroy! Есть примеры, где объект потока уничтожается при нажатии на кнопку, вот там ссылка обнуляется и есть объяснение зачем это делается.
10 июл 20, 15:31    [22165349]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Bred eFeM
Member

Откуда:
Сообщений: 550
DmSer,
Респект за работу!

Рекомендую назвать материал - "Памятка изучающим (многопоточное программирование на) Delphi TThread"

+
(руки пока не дошли до описания темы синхронизации между потоками, а это, я считаю, очень важно).
Мдя... (может рассказать о нескольких способах кормления философов на примерах?)
11 июл 20, 19:49    [22165803]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Bred eFeM
Мдя... (может рассказать о нескольких способах кормления философов на примерах?)


Я не уверен в пользе такого подхода. Помню, на 2-м или 3-м курсе университета были занятия, на которых преподавали многопоточность по философам (библиотека Gala), анимация интересная, но вряд ли кто-то из студентов смог извлечь из неё что-то полезное. А преподаватель вообще был не знаком с этой библиотекой :)

Сообщение было отредактировано: 12 июл 20, 00:22
12 июл 20, 00:21    [22165886]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Учебник сохранён в формате markdown. Очень удобная вещь оказалась. Текст в итоге читается вроде не хуже, чем в docx. ссылка
28 июл 20, 20:05    [22174839]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
white_nigger
Member

Откуда: Тула
Сообщений: 2367
Не понравилось буквально в первом примере это:
procedure TMyThread.Execute;
var
  V: Int64;
begin
  FreeOnTerminate := True;
  V := DoLongCalculations;
  MyShowMessage('Результат: ' + IntToStr(V));
end;

Как только начинающий захочет заменить MyShowMessage на показ своей супер-пупер формы - он может нехило обломаться. Обязательно надо подчеркнуть что все UI вещи (по крайней мере VCL) надо выполнить в Synchronize или Queue. Понятно что в примере голый WinApi и там и так прокатит, но лучше сразу показать. Вместо апишного вызова лучше взять делфёвый ShowMessage
28 июл 20, 22:37    [22174890]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
white_nigger
Не понравилось буквально в первом примере это:
procedure TMyThread.Execute;
var
  V: Int64;
begin
  FreeOnTerminate := True;
  V := DoLongCalculations;
  MyShowMessage('Результат: ' + IntToStr(V));
end;

Как только начинающий захочет заменить MyShowMessage на показ своей супер-пупер формы - он может нехило обломаться. Обязательно надо подчеркнуть что все UI вещи (по крайней мере VCL) надо выполнить в Synchronize или Queue. Понятно что в примере голый WinApi и там и так прокатит, но лучше сразу показать. Вместо апишного вызова лучше взять делфёвый ShowMessage


В пояснении к этому примеру приводится необходимая информация о MyShowMessage и ShowMessage. Это сделано специально, чтобы читатель не пытался вызывать ShowMessage из доп. потока.
28 июл 20, 23:53    [22174909]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
Док
Member

Откуда: Казань
Сообщений: 6753
Пробежал по диагонали. Классная статья получилась. Для полноты картины еще бы неплохо добавить разделы про эвенты, мьютексы, семафоры. Я, например, про эвенты кое-как наскреб инфу в инете, потому методом проб и ошибок дотумкал, как они работают :)
29 июл 20, 14:28    [22175166]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1167
Док
Пробежал по диагонали. Классная статья получилась. Для полноты картины еще бы неплохо добавить разделы про эвенты, мьютексы, семафоры. Я, например, про эвенты кое-как наскреб инфу в инете, потому методом проб и ошибок дотумкал, как они работают :)


Спасибо!

Эвенты, мьютексы и семафоры - очень сложная часть. Пока не придумал, как это влить в статью. Мьютексы может сейчас и не особенно актуальны. На своей практике могу сказать, что мьютексы полезны в случае, если нужно синхронизировать работу нескольких экземпляров программы (в том числе реализовать контроль повторного запуска приложения). В рамках одной программы они не нужны, можно их заменить крит. секцией либо TMonitor. Эвенты чаще используем, но только в рамках одной программы (т.е. без межпроцессного взаимодействия). В основном в обмене по RS-232. TMonitor их также может заменить. Семафоры вообще не используем, имхо, проще использовать крит.секцию + счётчик чем разбираться с ещё одним объектом синхронизации.
Нужно ещё учитывать кроссплатформенность, иначе можно кучу времени потратить на то, что является сложным, windows-ориентированным и никому не нужным.

Раньше я очень часто использовал эвенты, мьютексы, может даже злоупотреблял ими в какой-то степени. Сейчас гораздо реже. Выяснилось, что очень многие вещи можно сделать на крит. секции и циклах ожидания со Sleep :). Может так получается небольшой оверхед, но программа становится проще.
29 июл 20, 15:42    [22175249]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11984
DmSer
и, как минимум, реализовать override-метод Execute.

и, как минимум, переопределить виртуальный метод Execute.


DmSer
⚠️ Запущенный поток не завершается при выходе из программы
Завершается
procedure _Halt0;
........
{$IF Defined(MSWINDOWS)}
      ExitProcess(ExitCode);
{$ELSEIF Defined(POSIX)}
      __exit(ExitCode);
{$ELSE}
{$MESSAGE ERROR 'Unknown platform'}
{$ENDIF}
      // never arrive hear.
    end;

    InitContext := InitContext.OuterContext^
  end;
end;
Но до выделенной строки дело может не дойти из-за финализации менеджера памяти.

Но я о чем - в Windows процесс живет, пока работает хотя бы один поток процесса, тогда как Delphi принудительно убивает процесс при завершении главного потока

DmSer
Ваша программа с большой вероятностью будет глючить.
Может имеет смысл обойтись без сленга?

DmSer
Также хочу отметить, что при срабатывании таймера не следует обращаться к базе данных из основного потока, лучше это делать из дополнительного потока, разумеется, в отдельном подключении.
Если мы говорим о мануале для новичков, то нифига это не разумеется. Если уже зацепил работу с БД, то явно укажи, что делать только так или смотреть документацию к СУБД. Тот же MySQL позволяет расшаривать соединение между потоками, при выполнении определенных условий

DmSer
ℹ️ Внимание! Если периодическая задача выполняется редко (например, каждые 10 минут), рекомендуется каждый раз (если это не сложно!) для такой задачи создавать новый поток. Вероятно, это лучше, чем часами удерживать дополнительный поток в спящем состоянии (особенно, если вы разрабатываете 32-разрядное Windows-приложение).
Чем лучше? Я бы наоборот делал бы обратную рекомендацию. Спящий поток есть не просит, а снаружи лучше управлять одним объектом, чем каждый раз создавать новый. Плюс дополнительное время на инициализацию нового потока


DmSer
⚠️ Внимание! Если поток переведён в спящее состояние с помощью функции Sleep, то не существует другого способа выйти из этого состояния кроме истечения указанного временного периода
Так зачем учить плохому? Есть две функции, которые можно использовать исключительно в тестовых приложениях и никогда в реальных Sleep() и Application.ProcessMessages. Новичкам об этих функциях вообще лучше не знать
29 июл 20, 16:17    [22175262]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11984
DmSer
procedure TForm1.FormDestroy(Sender: TObject);
begin
  // При закрытии программы необходимо завершить работу потока
  // и уничтожить объект потока MyThread
  if MyThread <> nil then
    MyThread.Free;
end;
Ну и в чем великий смысл выделенной строчки? Если
procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;
29 июл 20, 16:22    [22175264]     Ответить | Цитировать Сообщить модератору
 Re: Многопоточное программирование в Delphi для начинающих  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11984
DmSer
Если же мы решим объявить для такого потока переменную и будем пытаться с нею работать, то рискуем нарваться на ошибку доступа к памяти «Access Violation», поскольку объект потока может быть уничтожен в любой момент времени.
Верно только для случая, когда поток завершается сам
29 июл 20, 16:49    [22175286]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4 5   вперед  Ctrl      все
Все форумы / Delphi Ответить