powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Простой шаблон для работы с потоками
54 сообщений из 54, показаны все 3 страниц
Простой шаблон для работы с потоками
    #39760204
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет!
Вот решил сформировал такую мысль.
ЯПри работе с потоками, лучше всего использовать следующую элементарную концепцию:
Любой поток должен иметь 2 возможных исхода: Успех и ошибка.

В Делфи это сводиться к 2м обратным вызовам(синхронным): OnSuccess и OnError
В общем-то, такой же подход используется в Ajax.
Элементарно? - да, элементарно.
Очевидно? - да, очевидно
Но на Делфи я такого не видел.

Я это реализовал примерно так. Хоть это и не претендует на истину последней инстанции.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
unit Thread.Basic;

interface

uses
  System.Classes, System.SysUtils, System.Variants;

type
  TBasicThread = class(TThread)
  private
    FOnSuccess: TNotifyEvent;
    FOnExecute: TNotifyEvent;
    FOnError: TNotifyEvent;
    FErrorMessage: string;
    FThreadResult: Variant;
  protected
    procedure HandleException(const AErrorMessage:string);
    procedure DoOnExecute; virtual;
    procedure DoOnError; virtual;
    procedure DoOnSuccess; virtual;
    procedure InternalExecute; virtual;
    procedure Execute; override;
  public
    property OnExecute:TNotifyEvent read FOnExecute write FOnExecute;
    property OnError:TNotifyEvent read FOnError write FOnError;
    property OnSuccess:TNotifyEvent read FOnSuccess write FOnSuccess;
    property ErrorMessage:string read FErrorMessage;
    property ThreadResult:Variant read FThreadResult write FThreadResult;
    class function StartThread(AOnExecute, AOnSuccess, AOnError:TNotifyEvent):TBasicThread; overload;
  end;

implementation

{ BasicThread }

class function TBasicThread.StartThread(AOnExecute, AOnSuccess, AOnError: TNotifyEvent): TBasicThread;
begin
 Result:=TBasicThread.Create(True);
 Result.OnError:=AOnError;
 Result.OnSuccess:=AOnSuccess;
 Result.OnExecute:=AOnExecute;
 Result.FreeOnTerminate:=True;
 Result.Start;
end;

procedure TBasicThread.DoOnError;
begin
 if Assigned(OnError) and (not Terminated) then
  OnError(Self);
end;

procedure TBasicThread.DoOnExecute;
begin
 if Assigned(OnExecute) and (not Terminated) then
  OnExecute(Self);
end;

procedure TBasicThread.DoOnSuccess;
begin
  if Assigned(OnSuccess) and (not Terminated) then
   OnSuccess(Self);
end;

procedure TBasicThread.Execute;
begin
 InternalExecute;
end;


procedure TBasicThread.HandleException(const AErrorMessage: string);
begin
 FErrorMessage:=AErrorMessage;
 Synchronize(DoOnError);
end;

procedure TBasicThread.InternalExecute;
begin
 try
  DoOnExecute;
  Synchronize(DoOnSuccess);
 except on E:Exception do
  HandleException(E.Message);
 end;
end;

end.


И пример использования:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
private
   FBasicThread: TBasicThread;
   procedure OnThreadError(Sender:TObject);
   procedure OnThreadSuccess(Sender:TObject);
   procedure OnThreadExecute(Sender:TObject);

...

procedure TForm1.Button1Click(Sender: TObject);
begin
 if not Assigned(FBasicThread) then
  begin
   FBasicThread:=TBasicThread.StartThread(OnThreadExecute, OnThreadSuccess, OnThreadError);
   Button1.Enabled:=False;
  end;
end;

procedure TForm1.OnThreadError(Sender: TObject);
begin
 Label1.Font.Color:=clRed;
 Label1.Caption:=FBasicThread.ErrorMessage;
 FBasicThread:=nil;
 Button1.Enabled:=True;
end;

procedure TForm1.OnThreadExecute(Sender: TObject);
var
 AResult:Integer;
begin
 Randomize;
 Sleep(1000);
 AResult:=Random(100);
 if AResult>50 then
  raise Exception.CreateFmt('Error executing thread %d', [AResult])
   else
  FBasicThread.ThreadResult:=string.Format('Hello world, %d',[AResult]);
end;

procedure TForm1.OnThreadSuccess(Sender: TObject);
begin
 Label1.Font.Color:=clGreen;
 Label1.Caption:=VarToStr(FBasicThread.ThreadResult);
 FBasicThread:=nil;
 Button1.Enabled:=True;
end;

...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760228
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_B,

- Доктор, я жить буду?
- А смысл??

Зачем передавать треду кучу специализированных обработчиков, что, кстати, противоречит, в
общем смысле, принципам инкапсуляции, когда можно передать один лишь хэндл супервизора,
по которому посылать потом соответствующие сообщения, синхронно/асинхронно по вкусу.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760262
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BПри работе с потоками, лучше всего использовать следующую элементарную концепцию:
Любой поток должен иметь 2 возможных исхода: Успех и ошибка.

В такой концепции потоки не нужны тебе, поскольку она подразумевает, что кому-то
приходится ждать завершения потока.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760266
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovValery_BПри работе с потоками, лучше всего использовать следующую элементарную концепцию:
Любой поток должен иметь 2 возможных исхода: Успех и ошибка.

В такой концепции потоки не нужны тебе, поскольку она подразумевает, что кому-то
приходится ждать завершения потока.
Хоть интерфейс не морозится.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760270
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman,

- Михаил Сергеевич, все куры сдохли!
- Ничего, зато у меня еще много полезных идей!! (с) :D
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760279
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BПри работе с потоками, лучше всего использовать следующую элементарную концепцию:
Любой поток должен иметь 2 возможных исхода: Успех и ошибка.
Valery_BЭлементарно? - да, элементарно.
Очевидно? - да, очевидноВсё наоборот.
Поток - это просто выполняющийся код. Чем меньше он зависит от других потоков (и чем меньше другие потоки зависят от него и результатов его выполнения) - тем лучше.
Valery_BНо на Делфи я такого не видел.Повезло, а я видел много раз, в т.ч. на этом форуме. Чуть не каждый первый, обнаружив проблемы с синхронизацией данных между потоками, запускает поток и начинает ждать его окончания, или (еще хуже, но из той же оперы) засовывает код потока в synchronize.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760280
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_B
Код: pascal
1.
Result.FreeOnTerminate:=True;


А это - вишенка на торте. Этим еще и убиваешь возможность управления своим потоком.
Уже не говоря про грабли, которые возникнут при использовании в dll.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760287
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любой поток должен иметь еще один вариант исхода - прерван досрочно.
А Synchronize - это замаскированное под удобство зло
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760291
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Любой поток должен иметь еще один вариант исхода - прерван досрочно.
Terminate?
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760297
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Любой поток должен иметь еще один вариант исхода - прерван досрочно.
Что касается вариантов исхода потока, то всё придумано давно и изначально: функция потока возвращает ExitCode (В TThread - это свойство ReturnValue, в винде по хендлу потока его можно получить через GetExitCodeThread).
Но это всё, конечно, не интересно, а надо изобретать велосипеды новые и разные.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760307
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Любой поток должен иметь еще один вариант исхода - прерван досрочно.

Всё верно.
Но я не хотел перегружать описание.
wadmanTerminate?
Не совсем.
Terminate вызывается в любом случае.
Но есть и отмена. Например, как SMSS при выполнении запроса есть 3 варианта:
1. Успех
2. Ошибка
3. Отмена запроса (не явно)

Как понятно, отмена запроса в таком случае может быть и не вызвана.
И когда она будет поток сможет выполнить "отмену" - неизвестно.
Но когда бы он его не отменил, пусть выполнит сразу выполнит OnCancel .

Я делаю так:
Код: pascal
1.
 BasicThread.Cancel(OnCancel);
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760311
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BНе совсем.
Чем не угодил метод, который лишь флажок выставляет?
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760312
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockА это - вишенка на торте. Этим еще и убиваешь возможность управления своим потоком.

Своим потоком я могу управлять до тех пор, пока он работает.
Когда он не работает - я не могу им управлять.

Ты путаешь управление потоком с результатами его выполнения.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760314
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanЧем не угодил метод, который лишь флажок выставляет?
Valery_BTerminate вызывается в любом случае.

В не зависимости от того, была ли ошибка, не было ей или поток прерван.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760317
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BYuRockА это - вишенка на торте. Этим еще и убиваешь возможность управления своим потоком.

Своим потоком я могу управлять до тех пор, пока он работает.
Когда он не работает - я не могу им управлять.
При FreeOnTerminate=True ты не знаешь, работает он еще или уже нет.
Т.к. не знаешь даже, валидна ли еще ссылка на объект класса потока, или уже нет.
Valery_BТы путаешь управление потоком с результатами его выполнения.Нет.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760318
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BwadmanЧем не угодил метод, который лишь флажок выставляет?
Valery_BTerminate вызывается в любом случае.

В не зависимости от того, была ли ошибка, не было ей или поток прерван.
Вот смотрю на твое первое сообщение (тему) и не понимаю о чем ты споришь или чему возражаешь?

Василий сетовал на отсутствие возможности прервать, я ему ответил.
Что-то мне подсказывает, что события вызываются до Destroy.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760324
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockПри FreeOnTerminate=True ты не знаешь, работает он еще или уже нет.
Т.к. не знаешь даже, валидна ли еще ссылка на объект класса потока, или уже нет.

Я всегда знаю, выполняется поток или нет.
Valery_B
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 if Assigned(FBasicThread) then
  MessageBox('Thread is still running, are you sure you want to exit ?') ;
end;

procedure TForm1.OnThreadError(Sender: TObject);
begin
 ...
 FBasicThread:=nil;
end;

procedure TForm1.OnThreadSuccess(Sender: TObject);
begin
 ...
 FBasicThread:=nil;
end;
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760347
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BYuRockПри FreeOnTerminate=True ты не знаешь, работает он еще или уже нет.
Т.к. не знаешь даже, валидна ли еще ссылка на объект класса потока, или уже нет.

Я всегда знаю, выполняется поток или нет.
Valery_B
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 if Assigned(FBasicThread) then
  MessageBox('Thread is still running, are you sure you want to exit ?') ;
end;

procedure TForm1.OnThreadError(Sender: TObject);
begin
 ...
 FBasicThread:=nil;
end;

procedure TForm1.OnThreadSuccess(Sender: TObject);
begin
 ...
 FBasicThread:=nil;
end;




А, ну да, там же Synchronize - твой поток, если решит разрушиться, будет ждать, пока ты будешь пытаться им управлять.

Т.е. для того, чтобы управлять потоком, надо еще обязательно не забыть свойство OnTerminate выставить и в нём обнилять ссылку на объект (в твоём велосипедном случае - в двух местах). Очень удобно и красиво, чо.

Пользуйся на здоровье.
P.S. При этом не забывай, что Synchronize полностью не работает в консоли и в dll, в обычном оконном режиме - полность не работает до Application.Run, а даже если все необходимые условия выполнены - твои потоки будут постоянно ждать тормозов главного потока, и еще - будут время от времени появляться взаимные блокировки (при ожидании событий этих дочерних потоков - это часто надо), решать проблему которых придется героически.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760366
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

Ты пытаешься найти причины, что бы не использовать OnError/OnSuccess ?
Или говоришь о нюансах работы Delphi в консоли или dll ?
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760371
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockнадо еще обязательно не забыть свойство OnTerminate выставить и в нём обнилять ссылку на объект (в твоём велосипедном случае - в двух местах)
На счёт велосипеда - согласен. Случаев даже не 2, а 3 (не явный OnCancel).
Но да, можешь сделать ещё один CallBack - на OnTerminate.
Если это красивее - можно и так.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760380
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BТы пытаешься найти причины, что бы не использовать OnError/OnSuccess ?
Я давно нашел причины для того, чтобы никогда не использовать Synchronize (и из-за этого - OnTerminate). Не использовать OnError/OnSuccess я буду не только по этим (вполне достаточным) причинам, а и потому, что это архитектурно неверно - ждать (в любом виде) событий о результате действий потока.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760388
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

хм...
Да, наверное, надо переименовать TBasicThread в TGUIThread. Но сути это не меняет.

По поводу OnError/OnSuccess - это не моё изобретение. Это изобретение jQuery.
Я лишь озвучил его.
Думаю, большинство всё таки использует данную концепцию.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760391
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BЭто изобретение jQueryНе знаю, кто это, но сути дела это не меняет - это архитектурно неверно.
Valery_BДумаю, большинство всё таки использует данную концепцию.Это сути дела тоже не меняет.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760397
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BTGUIThread
Лучше другое придумай. Таким названием ты введешь людей в заблуждение - они подумают, что этот твой поток работает с гуи (рисует окна и т.п., т.е. имеет по умолчанию очередь выкрутки сообщений как минимум, такой "Бэйсик класс" как раз может быть полезен).

А ты назови лучше TBasicSynchronousThread - это ближе по смыслу.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760444
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторВ Делфи это сводиться к 2м обратным вызовам(синхронным): OnSuccess и OnError
В общем-то, такой же подход используется в Ajax.

Думаю, разработчики на JS такому подходу удивятся.
В JS давно есть промисы, которые устраняют необходимость писать каллбэки в виде разбросанных по коду функций.
А теперь есть ещё и async/await, который радикально упрощает асинхронное программирование и избавляет от необходимости в таких каллбэках.
Причем от программиста знание многопоточного программирования не требуется.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760557
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BНо на Делфи я такого не видел.


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
uses
  System.Threading;

procedure TForm3.Button1Click(Sender: TObject);
begin
  Button1.Enabled := False;
  TTask.Run(
    procedure
    var
      AResult: Integer;
    begin
      try
        Randomize;
        Sleep(1000);
        AResult := Random(100);
        if AResult > 50 then
          raise Exception.CreateFmt('Error executing thread %d', [AResult]);

        TThread.Synchronize(
          TThread.Current,
          procedure
          begin
            Label1.Font.Color := clGreen;
            Label1.Caption := string.Format('Hello world, %d',[AResult]);
            Button1.Enabled := True;
          end
        );

      except
        on E: Exception do
        begin
          Label1.Font.Color := clRed;
          Label1.Caption := E.ToString();
          Button1.Enabled := True;
        end;
      end;
    end
  ).Start();
end;
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760558
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TThread.Synchronize по желанию можно заменить на TThread.Queue в зависимости от контекста или задачи..
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760622
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite,

Обожаю анонимные методы...

Даже на программах вида Button1Click вводят в замешательство.
Что будет в реальных программах остаётся только догадываться.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760624
Valery_B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не все йогурты одинаково полезны.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760649
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valery_BX-Cite,

Обожаю анонимные методы...

Даже на программах вида Button1Click вводят в замешательство.
Что будет в реальных программах остаётся только догадываться.

Это говорит только о недостатке квалификации. Мир меняется, технологии меняются. Подходы к разработке меняются. Не использовать, только потому что не понятно - печально.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760651
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
X-CiteValery_BX-Cite,

Обожаю анонимные методы...

Даже на программах вида Button1Click вводят в замешательство.
Что будет в реальных программах остаётся только догадываться.

Это говорит только о недостатке квалификации. Мир меняется, технологии меняются. Подходы к разработке меняются. Не использовать, только потому что не понятно - печально.

Использовать только потому, что это "супер-пупер-новая технология" - вот это печально(и глупо).
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760655
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubX-Citeпропущено...


Это говорит только о недостатке квалификации. Мир меняется, технологии меняются. Подходы к разработке меняются. Не использовать, только потому что не понятно - печально.

Использовать только потому, что это "супер-пупер-новая технология" - вот это печально(и глупо).

В примере выше уместно... У вас контекст выполнения асинхронного метода... Код по успеху или ошибке находится в одном месте, он легко читаем в пределах одного экрана и определяем. Сохраняется инкапсуляция логики.

К тому же ничто не мешает, если нет замыканий, анонимный метод превратить в метод класса.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760662
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
X-Cite,

Чем хуже?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
uses
  System.Threading;
  
procedure TaskProc;
var
  AResult: Integer;
begin
      try
        Randomize;
        Sleep(1000);
        AResult := Random(100);
        if AResult > 50 then
          raise Exception.CreateFmt('Error executing thread %d', [AResult]);

        TThread.Synchronize(
          TThread.Current,
          procedure
          begin
            Label1.Font.Color := clGreen;
            Label1.Caption := string.Format('Hello world, %d',[AResult]);
            Button1.Enabled := True;
          end
        );

      except
        on E: Exception do
        begin
          Label1.Font.Color := clRed;
          Label1.Caption := E.ToString();
          Button1.Enabled := True;
        end;
      end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
  Button1.Enabled := False;
  
  TTask.Run(TaskProc).Start;
end;
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760670
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockЧто касается вариантов исхода потока, то всё придумано давно и изначально: функция потока возвращает ExitCode (В TThread - это свойство ReturnValue, в винде по хендлу потока его можно получить через GetExitCodeThread).
Но это всё, конечно, не интересно, а надо изобретать велосипеды новые и разные.
При этом, что для меня загадка, ReturnValue - protected
Valery_BПо поводу OnError/OnSuccess - это не моё изобретение. Это изобретение jQuery.

Когда осваиваешь ЯзыкN, появляется соблазн притащить в уже освоенный ЯзыкM кое-какие ништяки. Знакомо. Но не забывай, что у разных языков разная концепция. Что естественно для JS с коллбэками (по-другому просто в принципе было не сделать до появления async/await), то на Дельфи смотрится чужеродно.
По сабжу - мне непонятно, зачем OnSuccess и OnError, когда достаточно OnFinish(Success), что, в свою очередь, не сильно отличается от стандартного OnTerminate. А результат завершения можно возвращать через ReturnValue. То есть расширение класса съеживается до одной лишь обертки над Execute
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760671
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub,

Так, конечно, наглядней. Что естественно, т.к. при отсутствии анонимных методов код получается более разбитым на части, что всегда хорошо.

Плохо, что и ошибки и проблемы остались те же:
1. Будут разнообразные проблемы, вплоть до порчи памяти, при исключениях в потоке;
2. Отсутствие возможности управления этим потоком;
3. Вся та же масса потенциальных проблем и ограничений с Synchronize/Queue, что и всегда.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760679
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock,

1. Исключения - конечно надо передавать выше
2. Кто мешает послать потоку сообщение?
3. А какие ограничения у Queue?
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760722
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubX-Cite,

Чем хуже?

авторК тому же ничто не мешает, если нет замыканий, анонимный метод превратить в метод класса.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760744
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubYuRock,

1. Исключения - конечно надо передавать выше
2. Кто мешает послать потоку сообщение?
3. А какие ограничения у Queue?
1. Нет, там асинхронное обращение к VCL.
2. Возможно, если TTask такое позволит. Не шарю и проверять не хочу.
3. Те же, что и у Synchronize.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760746
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock2. Возможно, если TTask такое позволит. Не шарю и проверять не хочу.Да, забыл добавить. Послать потоку сообщение - это не синхронная операция, что мягко говоря часто не удобно, к тому же его еще обработать надо, это сообщение.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760749
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRockzinpubYuRock,

1. Исключения - конечно надо передавать выше
2. Кто мешает послать потоку сообщение?
3. А какие ограничения у Queue?
1. Нет, там асинхронное обращение к VCL.
2. Возможно, если TTask такое позволит. Не шарю и проверять не хочу.
3. Те же, что и у Synchronize.

1. А какая разница? Я обычно кидаю message в основной поток, как будет у него время обработает...
2. Позволит, его и спрашивать не надо :-)
3. Например?
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760754
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockzinpub,

Плохо, что и ошибки и проблемы остались те же:
1. Будут разнообразные проблемы, вплоть до порчи памяти, при исключениях в потоке;
2. Отсутствие возможности управления этим потоком;
3. Вся та же масса потенциальных проблем и ограничений с Synchronize/Queue, что и всегда.
1. Чем дополнительный поток отличается от основного? Судя вашей логике исключения в основном потоке также портят память.
2. Неужели?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
procedure TForm3.Button1Click(Sender: TObject);
begin
  Button1.Enabled := False;
  FTask := TTask.Run(
    procedure
    var
      AResult: Integer;
    begin

      var SyncSetResult :=
        procedure(const aColor: TColor; const aMessage: string)
        begin
          TThread.Synchronize(
            TThread.Current,
            procedure
            begin
              SetResult(aColor, aMessage);
            end
          );
        end;

      var ASyncSetResult :=
        procedure(const aColor: TColor; const aMessage: string)
        begin
          TThread.Queue(
            TThread.Current,
            procedure
            begin
              SetResult(aColor, aMessage);
            end
          );
        end;
       // На выбор, что больше нравится, синхронно или асихнронно.
      try
        Randomize;
        Sleep(1000);
        AResult := Random(100);

        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
        begin
          ASyncSetResult(clFuchsia, 'Task Cancelled');
          Exit;
        end;

        if AResult > 50 then
          raise Exception.CreateFmt('Error executing thread %d', [AResult]);

        Sleep(5000);

        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
        begin
          ASyncSetResult(clFuchsia, 'Task Cancelled');
          Exit;
        end;

        ASyncSetResult(clGreen, string.Format('Hello world, %d',[AResult]));

      except
        on E: Exception do
        begin
          if TTask.CurrentTask.Status = TTaskStatus.Canceled then
          begin
            ASyncSetResult(clFuchsia, 'Task Cancelled');
            Exit;
          end;

          ASyncSetResult(clRed, E.ToString());
        end;
      end;
    end
  ).Start();
end;

procedure TForm3.Button2Click(Sender: TObject);
begin
  FTask.Cancel();
end;

procedure TForm3.SetResult(const aColor: TColor; const aMessage: string);
begin
  Label1.Font.Color := aColor;
  Label1.Caption := aMessage;
  Button1.Enabled := True;
end;


3. Это называется правила использования возможностей. Вы же не пишете код как хотите, а придерживаетесь каких-то правил. Просто одни правила на слуху и известны всем, а другие не хотим принимать потому что они не слуху.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760765
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub1. А какая разница? Я обычно
Ну то обычно, а в коде ошибка. Ладно, это не важно, тем более - это был копипаст. Но я же приведенный пример описывал.

zinpub2. Позволит, его и спрашивать не надо :-)
Значит, TTask хранит и дает доступ к хендлу потока. Но для этого надо держать объект TTask. В примере его нет. Я же приведенный пример описывал.

zinpub3. Например?
Я их уже приводил много раз, в этом топике - в том числе.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760790
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite1. Чем дополнительный поток отличается от основного?Ничем. За исключением того, что в нем нельзя обращаться к VCL.
X-CiteСудя вашей логике исключения в основном потоке также портят память.Нет.

X-Cite2. Неужели?
Код: pascal
1.
FTask.Cancel();



1. В примере не было хранения экземпляра TTask. В новом примере, кстати, есть вопросы на счет его валидности (ну это ладно - в одном месте добавить if Assigned, в другом - Free, понятно). Короче, приходим к эквиваленту создания объекта TThread и нормальной работе с ним (при FreeOnTerminate=False, конечно).
2. А кроме Cancel? Что, по другому потоком управлять никогда не надо, кроме как попытаться его прервать? В случае с объектом TThread можно и удобно всё.

X-CiteYuRockzinpub,

Плохо, что и ошибки и проблемы остались те же:
1. Будут разнообразные проблемы, вплоть до порчи памяти, при исключениях в потоке;
2. Отсутствие возможности управления этим потоком;
3. Вся та же масса потенциальных проблем и ограничений с Synchronize/Queue, что и всегда.
1. Чем дополнительный поток отличается от основного? Судя вашей логике исключения в основном потоке также портят память.
2. Неужели?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
procedure TForm3.Button1Click(Sender: TObject);
begin
  Button1.Enabled := False;
  FTask := TTask.Run(
    procedure
    var
      AResult: Integer;
    begin

      var SyncSetResult :=
        procedure(const aColor: TColor; const aMessage: string)
        begin
          TThread.Synchronize(
            TThread.Current,
            procedure
            begin
              SetResult(aColor, aMessage);
            end
          );
        end;

      var ASyncSetResult :=
        procedure(const aColor: TColor; const aMessage: string)
        begin
          TThread.Queue(
            TThread.Current,
            procedure
            begin
              SetResult(aColor, aMessage);
            end
          );
        end;
       // На выбор, что больше нравится, синхронно или асихнронно.
      try
        Randomize;
        Sleep(1000);
        AResult := Random(100);

        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
        begin
          ASyncSetResult(clFuchsia, 'Task Cancelled');
          Exit;
        end;

        if AResult > 50 then
          raise Exception.CreateFmt('Error executing thread %d', [AResult]);

        Sleep(5000);

        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
        begin
          ASyncSetResult(clFuchsia, 'Task Cancelled');
          Exit;
        end;

        ASyncSetResult(clGreen, string.Format('Hello world, %d',[AResult]));

      except
        on E: Exception do
        begin
          if TTask.CurrentTask.Status = TTaskStatus.Canceled then
          begin
            ASyncSetResult(clFuchsia, 'Task Cancelled');
            Exit;
          end;

          ASyncSetResult(clRed, E.ToString());
        end;
      end;
    end
  ).Start();
end;

procedure TForm3.Button2Click(Sender: TObject);
begin
  FTask.Cancel();
end;

procedure TForm3.SetResult(const aColor: TColor; const aMessage: string);
begin
  Label1.Font.Color := aColor;
  Label1.Caption := aMessage;
  Button1.Enabled := True;
end;



3...одни правила на слуху и известны всем, а другие не хотим принимать потому что они не слуху.
Да, я не хочу принимать правила запрета использования моего кода и вообще продуктов в консоли, библиотеках.
Не хочу, чтобы мои потоки при синхронизации данных все до единого и всегда ждали главного потока (и, конечно, всех остальных потоков, которые во время этого ожидания тоже вызвали Sinchronize/Queue). Мне медленно.
И так далее.
Да, я такие правила не принимаю и не приму.

Благодаря таким правилам и продвижению таких архитектурных решений программы на Делфи (использующие такие решения) часто легко отличимы от других не в лучшую сторону, что неминуемо способствует и популяризации Делфи.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760882
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockНичем. За исключением того, что в нем нельзя обращаться к VCL.
В Java под Android тоже нельзя обращаться к GUI в дополнительных потоках. Однако это никому не создает никаких проблем.
YuRock1. В примере не было хранения экземпляра TTask. В новом примере, кстати, есть вопросы на счет его валидности (ну это ладно - в одном месте добавить if Assigned, в другом - Free, понятно). Короче, приходим к эквиваленту создания объекта TThread и нормальной работе с ним (при FreeOnTerminate=False, конечно).

Так вы документацию почитайте, чтобы не нести чушь.
YuRock2. А кроме Cancel? Что, по другому потоком управлять никогда не надо, кроме как попытаться его прервать? В случае с объектом TThread можно и удобно всё.

Потоки нужны чтобы выполнять задачи. Зачем ими управлять если ими управляет пул. Вы должны управлять задачами. Отправили задачу на параллельное выполнение и управляете ей.. какая вам разница, есть поток, нет потока... Пул сам создаст если надо или из очереди возьмет свободный и назначит ему задачу.
YuRockДа, я не хочу принимать правила запрета использования моего кода и вообще продуктов в консоли, библиотеках.
Не хочу, чтобы мои потоки при синхронизации данных все до единого и всегда ждали главного потока (и, конечно, всех остальных потоков, которые во время этого ожидания тоже вызвали Sinchronize/Queue). Мне медленно.

В любом языке изменение GUI идет через главный поток. Где-то это скрыто синтаксическим сахаром.
Я не понимаю, зачем ждать главный поток? У вас в нем трудоемкие задачи что-ли выполняются? Или изменение Caption у кнопки занимает N секунд?
Или может быть вы ничего не знаете о IFuture<T>?
YuRockБлагодаря таким правилам и продвижению таких архитектурных решений программы на Делфи (использующие такие решения) часто легко отличимы от других не в лучшую сторону, что неминуемо способствует и популяризации Делфи.
Благодаря вот таким древним взглядам Дельфи и не популярна.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39760903
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockБлагодаря таким правилам и продвижению таких архитектурных решений программы на Делфи (использующие такие решения) часто легко отличимы от других не в лучшую сторону, что неминуемо способствует и популяризации Делфи.та ну его такую популярность, больше 90% с многопоточкой вообще работать не умеет
каких только ляпов не нарисуют
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761026
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-CiteYuRockНичем. За исключением того, что в нем нельзя обращаться к VCL.
В Java под Android тоже нельзя обращаться к GUI в дополнительных потоках. Однако это никому не создает никаких проблем.
Для меня такое поведение тоже не проблема. К чему это сообщение?
Вы задали вопрос, я на него ответил, без задней мысли, с какой целью дальше последовала лекция про яву и андроид?
Кстати, в Делфи (Windows), к GUI можно обращаться из других потоков. Если это не VCL, конечно.

X-CiteТак вы документацию почитайте, чтобы не нести чушь.
Документацию по вашему примеру 21787355 ? Её не существует - Вы ведь её не предоставили. Так что приходится нести чушь (по Вашему мнению).

X-CiteПотоки нужны чтобы выполнять задачи. Зачем ими управлять
Это если себя ограничивать.

X-Citeесли ими управляет пул. Вы должны управлять задачами. Отправили задачу на параллельное выполнение и управляете ей.. какая вам разница, есть поток, нет потока... Пул сам создаст если надо или из очереди возьмет свободный и назначит ему задачу.

Зачем управлять? Чтобы его можно было приостановить, разбудить, изменить в нем какие-нибудь параметры, проверить состояние, наступление события и вообще всё что угодно. Всё. На вопрос "зачем" ответ таков: "для того, чего душе угодно".

X-CiteВ любом языке изменение GUI идет через главный поток
Не влюбом, в делфи - можно, выше писал, как (только какое отношение, опять же...).

X-CiteЯ не понимаю, зачем ждать главный поток?
Вот и я не понимаю, потому не использую Sinchronize (не только по этому, конечно).

X-CiteУ вас в нем трудоемкие задачи что-ли выполняются? Или изменение Caption у кнопки занимает N секунд?
Во всех программах они выполняются (время-ёмкие задачи). Та же инициализация программы (или какого-то её модуля), например, занимает сравнительно много времени и основного потока в том числе.
Синхронное ожидание какого-то события из другого потока (выполнение команды из очереди, например) занимает так же много времени. Это иногда надо.
Мало ли что.
Да само выполнение CheckSynchronize (если в очередь добавлялись задания) чего стоит со всеми его объектами синхронизации и т.п.
Да, всё это тормозит (что самое страшное - и другие потоки в том числе). Без необходимости.
X-CiteИли может быть вы ничего не знаете о IFuture<T>?
В этой фиче нет ничего нового. Просто еще развитие кривого механизма. Отношения к топику это не имеет.

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

X-CiteБлагодаря вот таким древним взглядам Дельфи и не популярна.
Дельфи не популярна в 1-ю очередь потому, что программы на ней - низкого качества. А низкого качества они потому, что программисты используют кривые архитектурные решения. К использованию которых их подталкивают их разработчики, разработчики библиотек, заюзавшие эти решения, и сообщения на форумах.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761029
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)YuRockБлагодаря таким правилам и продвижению таких архитектурных решений программы на Делфи (использующие такие решения) часто легко отличимы от других не в лучшую сторону, что неминуемо способствует и популяризации Делфи.та ну его такую популярность, больше 90% с многопоточкой вообще работать не умеет
каких только ляпов не нарисуют
Когда "отличимы от других не в лучшую сторону", то и популярность со знаком минус, естественно.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761033
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)больше 90% с многопоточкой вообще работать не умеет
Это как раз нормально. Вообще не просто представить в мозгу, как будет себя вести параллельная работа. Для этого ведь нужен этот самый мозг.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761041
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockДокументацию по вашему примеру 21787355 ? Её не существует - Вы ведь её не предоставили. Так что приходится нести чушь (по Вашему мнению).

http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_the_Parallel_Programming_Library

YuRockЗачем управлять? Чтобы его можно было приостановить, разбудить, изменить в нем какие-нибудь параметры, проверить состояние, наступление события и вообще всё что угодно. Всё. На вопрос "зачем" ответ таков: "для того, чего душе угодно".

Зачем это надо? Вы решаете бизнес-задачи. Управляйте задачами. Поток это инструмент выполнения задачи. Зачем вам их создавать будить, проверять состояние... Пусть этим занимается пул...
У вас сервер на 16 процессоров по 4 ядра... Итого 64 виртуальных процессора. Пул по умолчанию максимум может создать вам 64 потока.. Ну и пусть себе живут... Они же спят... Прилетает к ним задача, один проснулся - выполнил - заснул... Все..
Нет затрат ОС на создание/уничтожение потоков, нет затрат на смену контекста переключения между ними в рамках одного ядра.

Время когда надо мыслить низкоуровневыми примитивами давно ушло, сейчас это не выгодно. Решайте бизнес-задачи, а не велосипеды.

YuRockА низкого качества они потому, что программисты используют кривые архитектурные решения. К использованию которых их подталкивают их разработчики, разработчики библиотек, заюзавшие эти решения, и сообщения на форумах.

Низкого качества потому что криво используют нормальные архитектурные решения. Как привыкли в 90-ых так и используют.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761082
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-CiteYuRockДокументацию по вашему примеру 21787355 ? Её не существует - Вы ведь её не предоставили. Так что приходится нести чушь (по Вашему мнению).

http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_the_Parallel_Programming_Library
Не увидел по ссылке Вашего примера.
Это 3-й уже отсыл не по теме. Мне надоело. Дальнейшие такие буду игнорировать.

X-CiteЗачем это надо? Вы решаете бизнес-задачи. Управляйте задачами. Поток это инструмент выполнения задачи. Зачем вам их создавать будить, проверять состояние... Пусть этим занимается пул...
Повтор вопроса.
Пример повтора ответа.
Зачем приостановить задачу вместо того, чтобы убить её и пересоздать? Чтобы не выполнять после возобновления заново всю инициализацию. Например, подключение к базе/устройству, регистрация где-то.

Я не против пулов когда это удобно и надо. Я против усложнения логики и ухудшения производительности, при впихивании пулов туда, где это не надо.
X-CiteНизкого качества потому что криво используют нормальные архитектурные решения.
Не буду повторяться, только еще одно: если архитектурное решение легко использовать криво - значит оно криво спроектировано.
Особенно становится плохо, когда оказывается, что это решение невозможно использовать НЕ криво, а уже поздно - горы кода написаны.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761337
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
моё ИМХО об архитектуре TThread в VCL

большой косяк: несимметричные старт-стоп потока, то что старт в AfterConstruction - это хорошо, но вот то что ожидание остановки и остановка в деструкторе а не в BeforeDestruction рождает дурной код вроде

Код: pascal
1.
2.
3.
inherited Destroy;
// финализация
....




мало того что так накосячили с остановкой, не предоставили метод Stop (остановки и ожидания завершения), и его ещё не всякий сможет правильно написать (кто сомневается, попробуйте)


методы Synchronize и Queue - руки бы оторвать тому кто решил посылать что-то в пустоту, эти методы должны быть у того кто их обрабатывает, в VCL это TApplication
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761374
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Еще минус: нет возможности указать размер стека (хотя может щас и появилась, не знаю).
Поэтому, когда это надо, приходится использовать BeginThread.
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761586
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-CiteВремя когда надо мыслить низкоуровневыми примитивами давно ушло, сейчас это не выгодно. Решайте бизнес-задачи, а не велосипеды.Золотые слова! :)
...
Рейтинг: 0 / 0
Простой шаблон для работы с потоками
    #39761643
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_niggerX-CiteВремя когда надо мыслить низкоуровневыми примитивами давно ушло, сейчас это не выгодно. Решайте бизнес-задачи, а не велосипеды.Золотые слова! :)слова конечно хорошие, но в большинстве своём приходится работать с дырявыми абстракциями и некорректными реализациями, и это большая проблема текущего состояния RTL и VCL

PS: знаю что много чего специально MS подгадил, но проблемы надо решать, а не консервировать
...
Рейтинг: 0 / 0
54 сообщений из 54, показаны все 3 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Простой шаблон для работы с потоками
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]