powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Шаблон класса для работы с потоком (WThread, Thread)
25 сообщений из 469, страница 14 из 19
Шаблон класса для работы с потоком (WThread, Thread)
    #39323891
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Barmaley57defecatorне ляжет, на серваке со 128 гигами оперативы создалось чуть больше пяти миллионов потоков (которые TThread),
четыре процессора по 3.2 ГГц по четыре ядра на каждом плюс гипертрейд на каждом ядре.
Суммарная нагрузка была в районе 55-65 процентов.Гы!!! Стек потоков уменьшал с дефолта что-ли? Главное, чтобы стека хватило. Ну и ресурсов на обслуживание всего этого дела ОСь должна отхавать нехило. Тормоза сильно ощущались после этого выкрутаса?

мышка лагала сильно, а так внешне вроде несильно тормозила.
Оракля там ещё запущена, я с другого компа к ней цеплялся,
лаги при выполнении запросов были заметные
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39323892
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Barmaley57Опять таки, очереди сообщений то хватит, чтобы заюзать класс wadman'a?
кстати, про очереди в классе вадмана я что-то не подумал...
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39323897
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
defecatorBarmaley57Опять таки, очереди сообщений то хватит, чтобы заюзать класс wadman'a?
кстати, про очереди в классе вадмана я что-то не подумал...
Если очереди поломаются, то поменяй в wthread.inc режим на WTHREAD_LIBRARY.
Тогда будет использоваться TQueue для общения.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39327281
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Полноценная версия компоненты для батонометателей.
Признаться, мне и самому так нравится больше. :)

Теперь есть обертка над wthread, которая делает таски (TTask), которые тоже являются компонентами.
Пользоваться стало чуть проще и удобнее.
Пакет ставится в delphi и в lazarus для простоты.
Под *nix пока не проверял.
Код: 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.
unit main;

interface

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

type
  TfrmWCThreadDemo = class(TForm)
    Memo1: TMemo;
    butDemoTimer: TButton;
    WCThread1: TWCThread;
    TaskDemoTimer: TTask;
    procedure FormDestroy(Sender: TObject);
    procedure TaskDemoTimerExecute(Sender: TTask);
    procedure TaskDemoTimerFinished(Sender: TTask);
    procedure TaskDemoTimerProgress(Sender: TTask; const Value: Word);
    procedure butDemoTimerClick(Sender: TObject);
  private
  public
    procedure AddLog(const Text: string);
  end;

var
  frmWCThreadDemo: TfrmWCThreadDemo;

implementation

{$R *.dfm}

procedure TfrmWCThreadDemo.TaskDemoTimerExecute(Sender: TTask);
var i: integer;
begin
    // этот метод выполняется в другом потоке, в это время форму можно таскать и ничего не тормозит
    for I := 0 to Sender.Param-1 do begin
        // проверка на то, что поток еще выполняется
        if Sender.Terminated then exit;
        Sleep(1000);
        // сообщаем о прогрессе основной форме
        Sender.PostProgress(i+1);
    end;
end;

procedure TfrmWCThreadDemo.FormDestroy(Sender: TObject);
begin
    // обязательное условие, ожидание окончания работы задачи на случай закрытия формы при выполняющейся задаче
    WCThread1.FinishAllTasks;
end;

procedure TfrmWCThreadDemo.AddLog(const Text: string);
begin
    // добавляет сообщение в лог
    Memo1.Lines.Add(Format('%s : %s', [FormatDateTime('hh:nn:ss.zzz', Now), Text]));
end;

procedure TfrmWCThreadDemo.butDemoTimerClick(Sender: TObject);
begin
    // так запускается задача в другом потоке
    TaskDemoTimer.Start(20);
    AddLog(Format('%s %s', [TaskDemoTimer.Name, 'start']));
end;

procedure TfrmWCThreadDemo.TaskDemoTimerFinished(Sender: TTask);
begin
    // задача сообщила обо окончании работы
    // здесь можно запустить другую задачу (выполняется в основном vcl потоке)
    AddLog(Format('%s %s', [Sender.Name, 'finished']));
end;

procedure TfrmWCThreadDemo.TaskDemoTimerProgress(Sender: TTask; const Value: Word);
begin
    // выполняется в основном vcl потоке
    AddLog(Format('%s %s %d', [Sender.Name, 'progress', Value]));
end;

end..

...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39327283
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И сами пакеты для delphi и lazarus.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39327382
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На Убунту (16) тоже работает с парой приведений типов. :)
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39328028
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Протестировано в следующих комбинациях: Ubuntu 14, 16 (LTS), WinCE 5, Windows XP/7, Delphi XE2, Lazarus 1.6.
Работает. :)
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39328306
wadman,
может пора уже на гитхаб?
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39328494
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
серый-серый никможет пора уже на гитхаб?
я давно ему об этом говорил. И неплохо бы с демками...
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39328532
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доксерый-серый никможет пора уже на гитхаб?
я давно ему об этом говорил. И неплохо бы с демками...
А какая демка нужна?
Вроде уже проще некуда: бросил компоненту, накидал таски (которые как сообщения для потока) и вперед.
Без сарказма. Я думал, что теперь всё просто. Без ручного кода, всё в пределах основных принципов дельфи.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329216
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanбросил компоненту
вот видишь, теперь уже компонента. А я в первый раз об этом слышу, хотя за этим топиком внимательно слежу :)
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329218
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanБез ручного кода
а я по старинке, ручками. Только пару функций из твоего модуля использую ...
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329287
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Докwadmanбросил компоненту
вот видишь, теперь уже компонента. А я в первый раз об этом слышу, хотя за этим топиком внимательно слежу :)
Это появилось ровно на этой странице.
Выше описано.

ДокwadmanБез ручного кода
а я по старинке, ручками. Только пару функций из твоего модуля использую ...
NewString/FreeString?
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329298
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman,

в D7 не работает?
у меня при установке [Error] wthread.pas(357): Undeclared identifier: 'FHandle'

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
function TWEvent.GetHandle: THandle;
begin
    {$IFDEF WINCE}
    result := FWHandle;
    {$ELSE}
    result := FHandle;
    {$ENDIF}
end;
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329300
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

видимо нет, не тестировал. Завтра посмотрю.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329479
Кар-Кар
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почему такой большой? Зачем вы тащите все эти Classes...

Немного творчества и, в качестве идеи:
Код: pascal
1.
2.
    function WaitForMultipleThreads(Quantity:DWORD;const Parameter:Pointer;
      const WaitAll:BOOL;const Milliseconds:DWORD;const Proc:TCallback):DWORD;


Все. Одна функция на все случаи жизни. AsyncCall напоминает, но там опять всякие Classes, SysUtils и т.п., а выше чисто Windows.

Набросал эскиз:
Код: 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.
  TMTACallback = reference to function (Parameter:Pointer;const ThreadIndex,ThreadCount:DWORD):Integer;
  TMTA = class
  private type
  
    PThread = ^TThread;
    TThread = record
      Param  : Pointer;
      Proc   : TMTACallback;
      Index  : DWORD;
      Count  : DWORD;
      Signal : THandle;
      Handle : THandle;
      Id     : TThreadID; 
    end;
    
  private
    FThreads   : array [0..63] of TThread;
    FSignals   : array [0..63] of THandle;
  public
    function WaitForMultipleThreads(Quantity:DWORD;const Parameter:Pointer;
      const WaitAll:BOOL;const Milliseconds:DWORD;const Proc:TMTACallback):DWORD;
  end;

implementation

function ThreadExecute(Parameter:Pointer):Integer;
var
Thread : TMTA.PThread;
begin
Thread := TMTA.PThread(Parameter);
Result := Thread^.Proc(Thread^.Param, Thread^.Index, Thread^.Count);
SetEvent(Thread^.Signal);
end;

function ThreadCreate(var Thread:TMTA.TThread):Boolean;
begin
Thread.Signal := CreateEvent(nil,True,False,nil);
if Thread.Signal = 0 then Exit(False);
Thread.Handle := BeginThread(nil,0,@ThreadExecute,Pointer(@Thread),CREATE_SUSPENDED,Thread.Id);
if Thread.Handle <> 0 then Exit(True);
CloseHandle(Thread.Signal);
Result := False;
end;

function TMTA.WaitForMultipleThreads(Quantity:DWORD;const Parameter:Pointer;
  const WaitAll:BOOL;const Milliseconds:DWORD;const Proc:TMTACallback):DWORD;
var
i     : DWORD;
Count : DWORD;
begin
if Quantity > 64 then Exit(WAIT_FAILED);
Count := 0;
Quantity := (Quantity-1) and $7F; 
repeat
  if ThreadCreate(FThreads[Count]) then
  begin
    FThreads[Count].Param := Parameter;
    FThreads[Count].Proc := Proc;
    FThreads[Count].Index := Count;  
    FSignals[Count] := FThreads[Count].Signal;
    Inc(Count);
  end else
  begin
    Dec(Quantity);
  end;
until Count >= Quantity;
for i := 0 to Count-1 do
begin
  FThreads[i].Count := Count;
  ResumeThread(FThreads[i].Handle);
end;  
Result :=  WaitForMultipleObjects(Count,@FSignals[0],WaitAll,Milliseconds);
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.
  with TMTA.Create do
  try
    case WaitForMultipleThreads(4,Pointer(List),True,INFINITE,
      function (Parameter:Pointer;const ThreadIndex,ThreadCount:DWORD):Integer
      var
      List  : TStringList;
      I     : Integer;
      D     : Integer;
      Z     : Integer;
      Start : Integer;
      Stop  : Integer;
      begin
      List := TStringList(Parameter);
      D := List.Count div ThreadCount;
      Z := ThreadIndex + 1;
      Start := (Z - 1) + (D * (Z - 1));
      if Z <> ThreadCount then
        Stop := (Z + (D * Z)) - 1 else
        Stop := List.Count-1;
      for I := Start to Stop do
        List[I] := '#'+IntToStr(I)+'   '+List[I];
      end) of
    WAIT_OBJECT_0:
      begin

      end;
    end;
  finally
    List.SaveToFile('D:\out.ini');
    Free;
  end;

И сработал! Как ни странно, но все линии пронумеровались нормально. В будущем если: вызывать с WaitAll = False, чтобы возвращаться если кто-то отработал и т.к. вызов из главного, то можно будет кое-чего в UI обновить безопасно - автоматический синхронайз фактически. Каллбэк переделать, чтобы вместо ThreadIndex/ThreadCount была какая-нибудь структура ThreadContext где можно было бы даже другими потоками поуправлять. Типа там Int64 с 64-мя битами(как раз максимальное поддерживаемое), которые отвечают за запущенность параллельных; через атомарный OR/AND брать и включать/отключать.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329531
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кар-КарЗачем вы тащите все эти Classes...
Один пишет "сделай компонет", другой "зачем classes". :)

Далее обсудим, когда расскажешь, на каких платформах это работает и что это делает?
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329719
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Допилил под Delphi 7.

Демо-код такой-же, как и под ubuntu и wince.
Код: 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.
unit main;

interface

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

type
  TForm1 = class(TForm)
    WCThread1: TWCThread;
    TaskDemoTimer: TTask;
    Memo1: TMemo;
    butDemoTimer: TButton;
    procedure butDemoTimerClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure TaskDemoTimerExecute(Sender: TTask);
    procedure TaskDemoTimerFinished(Sender: TTask);
    procedure TaskDemoTimerProgress(Sender: TTask; const Value: Word);
  private
    { Private declarations }
  public
    procedure AddLog(const Text: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AddLog(const Text: string);
begin
  Memo1.Lines.Add(Format('%s : %s', [FormatDateTime('hh:nn:ss.zzz', Now), Text]));
end;

procedure TForm1.butDemoTimerClick(Sender: TObject);
begin
  Memo1.Lines.Clear;
  AddLog(Format('Processor count: %d', [WCThread1.ProcessorCount]));
  TaskDemoTimer.Start(20);
  AddLog(Format('%s %s', [TaskDemoTimer.Name, 'start']));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  WCThread1.FinishAllTasks;
end;

procedure TForm1.TaskDemoTimerExecute(Sender: TTask);
var i: integer;
begin
  // another thread
  for i := 0 to Sender.Param-1 do begin
    if Sender.Terminated then exit;
    Sleep(1000);
    Sender.PostProgress(i);
  end;
end;

procedure TForm1.TaskDemoTimerFinished(Sender: TTask);
begin
  AddLog(Format('%s %s', [Sender.Name, 'finished']));
end;

procedure TForm1.TaskDemoTimerProgress(Sender: TTask; const Value: Word);
begin
  AddLog(Format('%s %s %d', [Sender.Name, 'progress', Value]));
end;

end.

...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329960
gssbox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
К моему удивлению, компонент установился и заработал в Lazarus на Ubuntu Mate 15.04 на миниПК с ARM процессором.
Пришлось только добавить в файл lpr проекта перед uses строчку {$DEFINE UseCThreads}, иначе приложение с тестовым примером вылетало с ошибкой RunError(232).
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329966
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gssboxПришлось только добавить в файл lpr проекта перед uses строчку {$DEFINE UseCThreads}, иначе приложение с тестовым примером вылетало с ошибкой RunError(232).
В wthread.pas warning имеется, но на него видимо мало кто обращает внимание в окошке компиляции...
Код: pascal
1.
2.
3.
4.
5.
    {$IFDEF UNIX}
        {$Message WARN 'WTHREAD: Add cthreads and cmem units to a project file.'}
        //cthreads,
        //cmem,
    {$ENDIF}



А вообще, об этом пишется почти в каждой теме про лазарус и многопоточность.
"Подошел к писуару, расстегни ширинку".
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329979
gssbox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот кстати интересный момент когда раскомментил cthreads в файле wthread.pas:
Код: pascal
1.
2.
3.
4.
5.
 {$IFDEF UNIX}
        {$Message WARN 'WTHREAD: Add cthreads and cmem units to a project file.'}
        cthreads,
        cmem,
    {$ENDIF}



то ошибка вылетала все равно, помогло только описанное выше изменение в файле WThreadTask.pas:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
program WThreadTask;

{$mode objfpc}{$H+}
{$DEFINE UseCThreads} //Здесь добавил эту строчку
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, TstWThread
  { you can add units after this };

{$R *.res}

begin
  RequireDerivedFormResource:=True;
  Application.Initialize;
  Application.CreateForm(TfrmWCThreadDemo, frmWCThreadDemo);
  Application.Run;
end.   
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329986
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gssboxВот кстати интересный момент когда раскомментил cthreads в файле wthread.pas:
Тут и не поможет. Модули cthreads и cmem должны быть самыми первыми модулями для проекта, а не для модуля.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39329990
gssbox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну так cthreads и был первым для проекта(см. выше), но заработало без ошибок только после добавления
{$DEFINE UseCThreads} перед uses.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39330009
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gssboxНу так cthreads и был первым для проекта(см. выше), но заработало без ошибок только после добавления
{$DEFINE UseCThreads} перед uses.
"Был" не значит, что использовался.
О чем спор? Что я не достаточно тонко намекаю на этот факт текстом сообщения?
gssbox
Код: pascal
1.
Add cthreads and cmem units to a project file.
...
Рейтинг: 0 / 0
Шаблон класса для работы с потоком (WThread, Thread)
    #39330012
gssbox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да спора нет, просто поделился информацией. Я на Lazarus только начал работать и у него есть свои не очевидные для меня нюансы.
...
Рейтинг: 0 / 0
25 сообщений из 469, страница 14 из 19
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Шаблон класса для работы с потоком (WThread, Thread)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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