Entwickler-Ecke

Delphi Tutorials - Thread-Programmierung unter Windows mit Delphi


Delete - So 21.09.03 14:49
Titel: Thread-Programmierung unter Windows mit Delphi
Thread Programmierung unter Windows mit Delphi

Aus dem Inhalt


Homepage: http://delphitutorials.michael-puff.de


G-man - Di 23.09.03 15:31

Gutes Tutorial, hat mich weiter gebracht...


Delete - Di 23.09.03 15:53

Danke. In der nächsten Version werden ein paar dieser fürchterlichen Dreckfuhler eleminiert sein. :roll:


focus - Do 25.09.03 16:16

TOP...Luckie weiter so
-super übersichtlich
-gute beispiele
-lerneffekt nonvcl + threads
=>klasse tut
gruss
michael


Delete - Mo 03.11.03 10:14

So, ich darf euch eine überarbeitet Fassung meines Threading Tutorials präsentieren. Es wurde grundlegend überarbeitet und ergänzt mit ein paar Worten zum dem VCL Thread-Objekt.

aus dem Inhalt:
– Grundlagen der Thread Programmierung
– Thread-Ablaufsteuerung
– Thread-Prioritäten
– Thread-Synchronisation
– Das Thread Objekt der VCL

Demos:
- CriticalSection
- InterLockedExchangeAdd
- Priority
- SpinLock
- ThreadTimes
- TThreadObject

Es ist jetzt insgesamt 33 Seiten stark.

Hier die Links:
Thread Tutorial Hauptseite [http://tutorials.luckie-online.de]


Udontknow - Mo 03.11.03 11:26

Hallo!

Respekt, Luckie, das ist ja wirklich übersichtlich und verständlich! :)

Du solltest unbedingt aber auch noch die Waitfor-Methode erläutern. Das ist z.B. bei dem Bestücken von DirectSound-Buffers für MP3-Wiedergabe sehr wichtig.

Cu,
Udontknow


G-man - Di 04.11.03 17:57

Und es wird wirklich immer besser...


Delete - Di 04.11.03 18:15

G-man hat folgendes geschrieben:
Und es wird wirklich immer besser...

Danke, so soll es auch sein.


Lhid - Mo 10.11.03 23:31

Mich und bitte alle meine Beiträge löschen. Habe mich und meine Meinung stark verändert


UC-Chewie - Mo 10.11.03 23:59

Bei mir gehts einwandfrei.


Delete - Di 11.11.03 11:34

@Chewie: Es konnte bei dir nicht gehen, die direkten Links waren fehlerhaft. Aber du warst wahrscheinlich so clever und bist dem Link zur Tutorialseite gefolgt. :wink:


UC-Chewie - Di 11.11.03 15:46

Hm, könntest recht haben :wink:


Sebastian01 - Di 18.11.03 13:10

rieeesssiggg - DANKE !

:mrgreen: :mrgreen: :mrgreen: :mrgreen:


jaenicke - Mo 05.01.04 14:17
Titel: Link
Hallo!

Das Tutorial ist echt super!

Es wär nur schön, wenn Du den Link am Anfang dieses Threads korrigieren würdest. :D (Da steht unter "Download des Tutorials" thread_tutorial.zip statt threads_tutorial.zip :cry: )

Das wäre dann etwas einfacher, als auf der HP danach zu suchen, auch wenn es da leicht zu finden ist!

MfG,
S.J.


cbs - Sa 31.07.04 11:44

hallo Luckie

dein tut ist erste sahne! viele infos und dazu noch verständlich verpackt. respekt!

ich hab aber leider doch eine frage zur Synchronize funktion:

du schreibst im tut:

Zitat:
Wichtig ist, so lange die zugehörige Synchronize Methode aus dem Haupt-VCL-Thread ausgeführt wird, steht der
Thread. Um nun zu verhindern, dass es zu Performance-Einbußen kommt, sollten die Synchronisations methoden so
kurz wie möglich gehalten werden.


ist damit "nur" die reine Synchronize Methode gemeint oder auch die Methoden die die Synchronize Methode aufruft?

spich: wird der thread direkt nach dem beenden der Synchronize Methode weiter ausgeführt (also ist es dem thread quasi egal das

Form1.UpdateLVCaption(FIndex, FCount);

noch abgearbeitet werden muss) oder wartet der thread bis die letzte anweisung von


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.UpdateLVCaption(Index, Count: Integer);
begin
  Listview1.Items[Index].SubItems[0] := 'Position: ' + IntToStr(Count);
  if Count = 10000 then
    Listview1.Items[Index].SubItems[0] := 'fertig';
end;


ausgeführt wurde?!

danke schon mal für eine antwort

mfg

cbs


Udontknow - Sa 31.07.04 14:35

Der Thread wartet, während der VCL-Haupt-Thread die per Synchronize übergebene Methode vollständig ausgeführt hat, das impliziert dann natürlich auch alle anderen Aufrufe, die in dieser Methode vorkommen.

Cu,
Udontknow


cbs - Sa 31.07.04 15:01

alles klar Udontknow danke dir!


BenBE - Mo 02.08.04 20:52

Die angegebenen Links funzen bei mir nicht. Meldet mir nur ne 404 (File not found).


Delete - Mo 02.08.04 22:00

So jetzt geht es.


Delete - Do 30.09.04 02:26

Ich habe das Threading Tutorial für Delphi erweitert und überarbeitet. Aus dem Inhalt:

Zu jedem Kapitel sind ein oder mehrer Demos im Zip-Archiv mitenthalten.

Downloadlink: http://tutorials.luckie-online.de

Fragen, Anregungen und Probleme könne entweder hier oder in meinem Support-Forum [http://www.luckie-online.de/forum/viewforum.php?f=1] gestellt werden.


Anonymous - Sa 02.10.04 16:13

cbs hat folgendes geschrieben:
Zitat:
Wichtig ist, so lange die zugehörige Synchronize Methode aus dem Haupt-VCL-Thread ausgeführt wird, steht der
Thread. Um nun zu verhindern, dass es zu Performance-Einbußen kommt, sollten die Synchronisations methoden so
kurz wie möglich gehalten werden.


ist damit "nur" die reine Synchronize Methode gemeint oder auch die Methoden die die Synchronize Methode aufruft?

spich: wird der thread direkt nach dem beenden der Synchronize Methode weiter ausgeführt (also ist es dem thread quasi egal das
Der Trick an Synchronize ist, daß es zwar zum Thread-Objekt gehört, aber nicht im Thread-Kontext (welchen das Objekt eigentlich repräsentieren soll) läuft, sondern im Kontext des Hauptthreads. Der Name verrät schon einiges - die Methode sollte nur eingesetzt werden um zB VCL-Elemente (Fortschrittsanzeige) mit den Daten des Threads zu synchronisieren.


wdbee - Sa 05.03.05 10:35

@Luckie: Hut ab, das ist gut.

Aber hier ein kleiner Hinweis zum Thema IPC (Inter Process Communication):

Luckie hat folgendes geschrieben:

Auf der anderen Seite gibt es aber auch Ressourcen, die von den Prozessen geteilt werden
können. Da wären zum Beispiel dynamische Bibliotheken, die DLL's, zu nennen. Eine DLL
kann von mehreren Prozessen gleichzeitig genutzt werden. Dabei wird sie nur einmal geladen,
ihr Code aber in den Adressraum des Prozesses eingeblendet, welcher die DLL nutzt. Dies
kann man unter anderem zur Inter Process Communication nutzen. Dies hat aber des Weiteren
noch den Vorteil, dass gleicher Code nur einmal geschrieben werden muss und gleichzeitig
von mehreren Prozessen genutzt werden kann.


Das war mal so. Aber heute stimmt das nicht mehr!

In der Delphihilfe (D5) steht dazu:

(a) In einer DLL deklarierte globale Variablen können von Object-Pascal-Anwendungen nicht importiert werden.
(b) Eine DLL kann von mehreren Anwendungen gleichzeitig verwendet werden. Jede Anwendung verfügt aber in ihrem Verarbeitungsbereich über eine Kopie der DLL mit einem eigenen Satz globaler Variablen.
(c) Damit mehrere DLLs (oder mehrere Instanzen einer DLL) den Speicher gemeinsam nutzen können, müssen die DLLs Speicherzuordnungstabellen verwenden. Weitere Informationen zu diesem Thema finden Sie in der Dokumentation der Windows-API.

Zu (a): Das ist etwas ungeschickt formuliert, denn es ist ja durchaus möglich auf in einer DLL deklarierte globale Variablen zuzugreifen, wenn man selbst passende Funktionen dafür vorsieht.
(Siehe auch das Beispiel unten)

Zu (b): Das mit der eigenen Kopie ist das neue, denn früher existierte nur eine Instanz. Darum kann man eine DLL normalerweise nicht mehr für IPC verwenden.

Zu (c): Das weiß wohl kaum jemand, und deshalb werden die meisten, die IPC per DLL implementieren auf die Nase fallen!

Deshalb der Vorschlag, nimm das einfach raus, denn das gehört dort nicht unbedingt zum Thema.

Für alle, die das nachprüfen wollen, ist unten ein Beispiel. Die DLL hat eine globale Variable,
die beim Laden initialisiert wird. Wenn ein Programm die Get-Funktion aufruft, erhält sie den aktuellen Wert. Mit der Set-Funktion lässt sich der Wert in der DLL ändern.

Wenn nun zwei Instanzen des Test-Programms gleichzeitig laufen, und jeweils eigene Namen per Set eintragen, sieht jeder, wenn er in allen Instanzen noch die Getfunktion benutzt, dass die Werte nicht übereinstimmen. Jede Instanz hat ihre eigene Kopie der DLL. Deshalb ist es also Essig mit IPC.

1. DLL-Projektdatei

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
library DLL;

uses
  SysUtils,
  Classes,
  UnitDLL in 'UnitDLL.pas';

  exports
  GetMyGlobalName,
  SetMyGlobalName;

{$R *.RES}

begin
end.


2. DLL-Implementation

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

interface

function GetMyGlobalName: ShortString; stdcall;
procedure SetMyGlobalName(Value: ShortString); stdcall;

implementation

var
  dllMyGlobalName: ShortString;

function GetMyGlobalName: ShortString;
begin
  Result := dllMyGlobalName;
end;

procedure SetMyGlobalName(Value: ShortString);
begin
  dllMyGlobalName := Value;
end;

initialization
  dllMyGlobalName := 'Jungfrau';
end.


3. Testprogramm:

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 UnitFormMain;

interface

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

type
  TFormMain = class(TForm)
    EditShowName: TEdit;
    LabelName: TLabel;
    LabelNewName: TLabel;
    EditNewName: TEdit;
    ButtonSetName: TButton;
    ButtonGetName: TButton;
    procedure ButtonGetNameClick(Sender: TObject);
    procedure ButtonSetNameClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  FormMain: TFormMain;

implementation

var
  cMyDLL: THandle;
  cGetNameProc: function: ShortSTring; stdcall;
  cSetNameProc: procedure (Name: ShortSTring); stdcall;

{$R *.DFM}

procedure TFormMain.ButtonGetNameClick(Sender: TObject);
begin
  EditShowName.Text := cGetNameProc;
end;

procedure TFormMain.ButtonSetNameClick(Sender: TObject);
begin
  cSetNameProc(EditNewName.Text);
  EditShowName.Text := cGetNameProc;
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  ButtonGetNameClick(nil);
end;

initialization
  cMyDLL := LoadLibrary('DLL.dll');
  @cGetNameProc := GetProcAddress(cMyDLL,'GetMyGlobalName');
  @cSetNameProc := GetProcAddress(cMyDLL,'SetMyGlobalName');

finalization
  cGetNameProc := nil;
  cSetNameProc := nil;
  if cMyDLL <> 0 then
    FreeLibrary(cMyDLL);
end.


4. Formular

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:
object FormMain: TFormMain
  Left = 498
  Top = 332
  Width = 182
  Height = 171
  ActiveControl = EditNewName
  Caption = 'Test Global DLL-Name'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  Position = poDefaultPosOnly
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object LabelName: TLabel
    Left = 8
    Top = 8
    Width = 87
    Height = 13
    Caption = 'Global DLL-Name:'
  end
  object LabelNewName: TLabel
    Left = 8
    Top = 56
    Width = 63
    Height = 13
    Caption = '&Neuer Name:'
    FocusControl = EditNewName
  end
  object EditShowName: TEdit
    Left = 8
    Top = 24
    Width = 153
    Height = 21
    Color = clBtnFace
    ReadOnly = True
    TabOrder = 0
  end
  object EditNewName: TEdit
    Left = 8
    Top = 72
    Width = 153
    Height = 21
    TabOrder = 1
  end
  object ButtonSetName: TButton
    Left = 88
    Top = 104
    Width = 75
    Height = 25
    Caption = '&Set Name'
    TabOrder = 2
    OnClick = ButtonSetNameClick
  end
  object ButtonGetName: TButton
    Left = 8
    Top = 104
    Width = 75
    Height = 25
    Caption = '&Get Name'
    TabOrder = 3
    OnClick = ButtonGetNameClick
  end
end


5. Test-Projekt

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
program Test;

uses
  Forms,
  UnitFormMain in 'UnitFormMain.pas' {FormMain};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TFormMain, FormMain);
  Application.Run;
end.


uall@ogc - Sa 05.03.05 11:11

klar hat die dll immer ne ganz eigene kopie sonst würde ja auch nen API hook auf die kernel32.dll alles crashen ;>
das funktioniert nur bei win98 im speicherbereich > 0x80000000 unter NT kann man FileMapping benutzen


beha - Fr 30.12.05 01:09

Hallo,

ich wollte gerade den Thread-Tutorial herunterladen und habe mich hierzu soeben hier (Delphi-Library) registriert (und nach Erhalt der EMail aktiviert).

Anschließend habe ich mich im Support-Forum von Luckie (Michael) registriert, aber dennoch komme ich beim Klick auf obigen Link immer hierhin (und nicht weiter):

http://tutorials.luckie-online.de/user/index.php

Wo muss ich mich noch registrieren, damit ich mit einem entsprechenden Username/password weiterkomme und das Tutorial herunterladen kann ?

Vielen Dank für eine Antwort.


raziel - Fr 30.12.05 17:04

Hallo,

Luckie ist "umgezogen" auf michael-puff.de, deshalb findest du das Tutorial, das du suchst wohl eher hier:
http://michael-puff.de/dirindex.php?folder=Developer/Delphi/Tutorials/

Werde den Link im ersten Posting entsprechend anpassen.

Gruß,
raziel


Delete - Mi 02.04.08 11:34

Ein neue überarbeitet und erweiterte Version ist erschienen.

Neu sind die Kapitel


Download des Tutorials und zugehörigen Demos im ersten Beitrag.


MDX - Fr 03.06.11 15:29

Da das Tutorial wieder nicht geht, hier der neue Link:

http://www.michael-puff.de/Programmierung/Delphi/Tutorials/Threads_mit_Delphi.pdf