Autor Beitrag
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8693
Erhaltene Danke: 172

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 26.01.16 10:41 
Hi,

heut von mir mal in der etwas ungewöhnlicheren Sparte ein Post.

Geht drum, ich habe eine Routine (wenige Zeilen), die auf Grund der darin verwendeten API zwingend auf einem eigenen Thread aufgerufen werden muss.

Für diese Routine muss ich 2 Parameter (Passen jeweils in einen Integer) übergeben.

Der startende Thread (in meinem Fall der Main Thread), soll auf den aufgerufnen Thread warten. Also in etwa:

ausblenden Vereinfachter Pseudocode:
1:
2:
3:
4:
5:
6:
7:
{
    auto thread = NEW_THREAD( [foo, bar]() {
        // ... Do some stuff that requires being run in the separate thread ...
    } );
    thread.start();
    thread.waitForExit();
}


Geht das auch irgendwie, ohne erst groß TThread komisch ableiten zu müssen?

Ach ja: Geht mir nicht um Performance, sondern kurze, übersichtliche Schreibweise.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18377
Erhaltene Danke: 1525

W10 x64 (Chrome, IE11)
Delphi 10.1 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 26.01.16 15:19 
Ich würde TTask verwenden, dieses Beispiel hatte ich dafür schon mal irgendwo gepostet:
ausblenden Delphi-Quelltext
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:
uses
  System.Threading;

var
  Tasks: array[0..1of ITask;
  a, b, c, d: Integer;
begin
  a := 42;
  b := 100;
  Tasks[0] := TTask.Create(
    procedure()
    begin
      Sleep(1000);
      c := a + b;
    end);
  Tasks[0].Start;
  Tasks[1] := TTask.Create(
    procedure()
    begin
      Sleep(3000);
      d := b - a;
    end);
  Tasks[1].Start;
  TTask.WaitForAll(Tasks);
  ShowMessage(IntToStr(c) + ' - ' + IntToStr(d));

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8693
Erhaltene Danke: 172

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 26.01.16 15:47 
Irgendwie meckert FPC bei mir bei System.Threading rum (";" erwartet, aber "." gefunden). Unit wird mit {$mode objfpc}{$H+} übersetzt, auch wenn das nicht das Problem sein dürfte.

Ansonsten ist das syntaktisch aber schon genau, wonach ich gesucht hatte :)

BTW: Lazarus 1.4.4 / FPC 2.6.4 in case it matters here.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18377
Erhaltene Danke: 1525

W10 x64 (Chrome, IE11)
Delphi 10.1 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 26.01.16 17:00 
Dann kann Lazarus das wohl nicht...
Vielleicht heißt die Unit aber auch nur anders. Das Beispiel stammt aus Delphi, ich hatte die Sparte übersehen.

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Moderator
Beiträge: 3647
Erhaltene Danke: 587

Win XP x86, Win 8.1 x64
Lazarus Snapshot; Delphi 7,2007,XE; PHP (PHPEdit,PhpStorm); JS; Java(Eclipse)
BeitragVerfasst: Di 26.01.16 18:35 
Warum TThread.CreateAnonymousThread noch keine Nestedprocvars kann ist mir nicht klar, wenn das drin wäre wär's die Antwort. So muss man das kurz selber bauen (das was du suchst ist TNestedThread, der generic steht da nur weil ich mal wissen wollte wie die Syntax dann aussieht):
ausblenden volle Höhe Delphi-Quelltext
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:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
unit Unit1;

{$mode objfpc}{$H+}
{$ModeSwitch nestedprocvars}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TNestedThread = class(TThread)
  public type
    TRunFunc = procedure is nested;
  private
    FFunc: TRunFunc;
  protected
    procedure Execute; override;
  public
    constructor Create(Func: TRunFunc);
  end;

  generic TDataThread<GData> = class(TThread)
  public type
    TRunFunc = procedure (Data: GData);
  private
    FData: GData;
    FFunc: TRunFunc;
  protected
    procedure Execute; override;
  public
    constructor Create(Data: GData; Func: TRunFunc);
  end;


var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure ThrdMethod(I: PInteger);
begin
  I^:= 1337;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  x, y: integer;

  procedure ThrdMethodN();
  begin
    X:= 42;
    Y:= 23;
  end;

begin
  TNestedThread.Create(@ThrdMethodN).WaitFor;
  ShowMessageFmt('x: %d, y: %d', [x, y]);

  (specialize TDataThread<PInteger>).Create(@X, @ThrdMethod).WaitFor;
  ShowMessageFmt('x: %d, y: %d', [x, y]);
end;

{ TNested }

procedure TNestedThread.Execute;
begin
  FFunc();
end;

constructor TNestedThread.Create(Func: TRunFunc);
begin
  inherited Create(true);
  FreeOnTerminate:= true;
  FFunc:= Func;
  {%H-}Resume;
end;


{ TDataThread }

procedure TDataThread.Execute;
begin
  FFunc(FData);
end;

constructor TDataThread.Create(Data: GData; Func: TRunFunc);
begin
  inherited Create(true);
  FreeOnTerminate:= true;
  FData:= Data;
  FFunc:= Func;
  {%H-}Resume;
end;

end.

WaitForMultiple etc. überlasse ich mal als einfache Übung dem Leser ;)

Edit: Oh, noch was: in den Mainthread zurück kommst du dann per TThread.Synchronize und .Queue, aber der Deadlock da drin wenn man das im Code oben tut dürfte offensichtlich sein. Die Variante für Nested wäre dann auch noch zu bauen.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Ich code EdgeMonkey -~==~- #ee-lounge in Freenode
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8693
Erhaltene Danke: 172

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 27.01.16 12:17 
Ist zwar nicht ganz so schön in-lambda-line, wie ich mir das erhofft hab, aber die TNestedThread-Klasse von Martok funzt wie gewünscht. Und Anfang der Methode ist grad noch so akzeptabel ;-)

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.