Entwickler-Ecke

Windows API - Eigenes Thread-Handle ermitteln


Heiko - Mo 25.12.06 20:05
Titel: Eigenes Thread-Handle ermitteln
Hallo Leuts,

inzwischen habe ich mich daran gewöhnt mit Threads zu arbeiten, da dadurch die GUI noch weiterhin flüssig reagiert, obwohl es noch genug zu tun gibt ;). Leider haben Threads den Nachteil, dass sie immer das maximum an Ressourcen verbrauchen, außer wenn man den mit sleep oder GetMessage abbremst. Da ja mein Thread auch mit dem Rest kummunizieren soll, habe ich mit für GetMessage entschieden, da ich dort auch keine Synchronisation zur Kommunikation brauche.
ICh stehe jetzt aber vor dem Problem das Thread-Handle zu bekommen, was ja BeginThread zurückgibt, aber leider nicht dem Thread selber mitteilt. Weiß einer von euch wie man aus dem Thread heraus ohne Synchronisation an das Thread-Handle kommt?

Grüße Heiko


BenBE - Mo 25.12.06 20:11

GetCurrentThread ;-)


Heiko - Di 26.12.06 10:57

Habe ich auch schon probiert, aber da bekomme ich den maximalen Cardinal zurück, stimmt also nicht :(.


Delete - Di 26.12.06 11:28

Sollte aber nicht der Fall sein:
Zitat:
GetCurrentThread

Retrieves a pseudo handle for the calling thread.


Heiko - Di 26.12.06 12:08

user profile iconLuckie hat folgendes geschrieben:
Sollte aber nicht der Fall sein:
Zitat:
GetCurrentThread

Retrieves a pseudo handle for the calling thread.

Das hatte ich bei MSDN auch gelesen, aber trotzdem bekomme ich nonsense zurück :(.

Mein Code:


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:
procedure TestThread(var ThreadID: Cardinal);
var
  Thread: Integer;
  msg: tagMSG;
begin
  Thread:=GetCurrentThread;
  while GetMessage(msg, Thread, 00do //Hier habe ich nen Haltepunkt um Thread auszuwerten
  begin
    if msg.message = WM_CREATE then
    begin
      Form1.Caption:='sdf';
    end;
  end;
  CloseHandle(Thread);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  ThreadID: Cardinal;
  Thread: Integer;
begin
  Thread:=BeginThread(nil0, @TestThread, @ThreadID, 0, ThreadID);
  ShowMessage(IntToStr(Thread)); //Vergleichswert ausgeben
  SendMessage(Thread, WM_CREATE, 00);
end;


BenBE - Di 26.12.06 13:58

Kannst Du mal kurz sagen, was GetLastError meldet? Bitte vor dem GetCurrentThread-Aufruf mit SetLastError auf 0 setzen, da die VCL häufig genug auch Fehlercodes ignoriert ...


Heiko - So 28.12.08 21:56

Um den Thread wieder auszugraben: GetLastError liefert 0 zurück und der Wert ist nicht MaxCardinal sondern -2 als Cardinal dargestellt.

Ich frage mich gerade nur: soll "pseudo handle" heißen, dass es nicht zum empfangen von Nachrichten geeignet ist, oder wie soll man es interpretieren?

Oder wie würdet ihr Messages im Thread empfangen?


jaenicke - So 28.12.08 22:19

Ich würde einfach TThread benutzen. ;-)

Dort kannst du z.B. die WndProc überschreiben. Und das Handle hast du auch direkt.


delfiphan - So 28.12.08 22:23

GetCurrentThreadId vielleicht? Ob das dem entspricht, was du suchst, weiss ich jetzt nicht. Ist jedenfalls eine systemweit eindeutige Id.


Heiko - So 28.12.08 22:25

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
GetCurrentThreadId vielleicht? Ob das dem Handle entspricht weiss ich nicht. Ist jedenfalls eine systemweit eindeutige Id.

Leider nein. Die Werte sind verschieden, die da herauskommen.

@TThread: Mal schauen, wie die das gemacht haben.


Delete - So 28.12.08 22:48

Versuch mal THandle als Datentyp zu nehmen. Das ist ein Cardinal in Delphi.

C#-Quelltext
1:
HANDLE WINAPI GetCurrentThread(void);                    

Und was ein Pseudohandle ist, wird in der Hilfe auch erklärt:
Zitat:
A pseudo handle is a special constant that is interpreted as the current thread handle. The calling thread can use this handle to specify itself whenever a thread handle is required.


Moderiert von user profile iconNarses: C in CS-Tag gewandelt


Heiko - So 28.12.08 22:59

user profile iconLuckie hat folgendes geschrieben Zum zitierten Posting springen:
Versuch mal THandle als Datentyp zu nehmen. Das ist ein Cardinal in Delphi.
[c]HANDLE WINAPI GetCurrentThread(void);[/c]

THandle ist auch nur ein Cardinal, von daher ist es wurscht, solange 32Bit 32Bit sind ;).
user profile iconLuckie hat folgendes geschrieben Zum zitierten Posting springen:
Und was ein Pseudohandle ist, wird in der Hilfe auch erklärt:

Äh ja: ich verstehe es so, dass es damals selber an sich arbeiten kann (komischer Ausdruck, ich weiß ;) ) - aber es klingt für mich so, als ob es ein anderes Handle sein könnte als das, worüber es von außen zu erreichen ist.


Heiko - Di 30.12.08 00:00

ICh habe mir jetzt mal TThread genauer angeschaut, also wie die es dort geregelt haben. Die übergeben einfach beim erzeugen die eigene Klasse und kommen so an das Handle ran.

Nun ich habe es ebenso gemacht, allerdings empfängt er nix auf dem Handle. Habe ich einen Fehler drin oder ist das Handle einfach nicht dafür geeignet?


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:
unit DanSo;

interface

uses
  Windows,

  DanSo_Messages,

  fmod;

type
  TDanSoPlayer = class(TObject)
  private
    FHandle: THandle;
  public
    constructor Create;
    procedure WndProc;
    destructor Destroy; override;
  end;

implementation

{ TDanSoPlayer }

function DanSoPlayerThread(DanSoPlayer: TDanSoPlayer): Integer;
begin
  //Start Message Loop
  DanSoPlayer.WndProc;
  Result:=0;
end;

constructor TDanSoPlayer.Create;
var
  ThreadID: Cardinal;
begin
  FHandle:=BeginThread(nil0, @DanSoPlayerThread, Pointer(Self), 0, ThreadID);
end;

destructor TDanSoPlayer.Destroy;
begin
  SendMessage(FHandle, WM_DanSo_Destroy, 00);
  WaitForSingleObject(FHandle, INFINITE);
  if FHandle <> 0 then CloseHandle(FHandle);
end;

procedure TDanSoPlayer.WndProc;
var
  msg: tagMSG;
begin
  while GetMessageW(msg, FHandle, 00do
  begin
    case msg.message of
      WM_DanSo_Destroy:
        begin
          break;
        end;
    end;
    TranslateMessage(msg);
    DispatchMessageW(msg);
  end;
end;

end.


@Luckie: THandle=Cardinal - ich hab nochmal nachgeschaut ;)