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
- Grundlagen (einen Threader zeugen/abspalten. Einen Thread beenden.)
- Steuerung von Threads (Anhalten/Fortsetzen)
- Threadprioritäten (Prozess-Prioritäten, Thread-Prioritäten, Programmieren von Prioritäten)
- Synchronisation von Threads (atomarerVariablenzugriff, KritischeAbschnitte)
- Der Stack eines Threads - neu in Version vom 2008-04-02
- Threadpools - neu in Version vom 2008-04-02
- Pseudo-Threads(Fibers) - neu in Version vom 2008-04-02
- Das VCL-Thread-OBjekt
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:
- Grundlagen der Thread Programmierung (BeginThread, ...)
- Thread-Ablaufsteuerung (ResumeThread, SuspendThread)
- Thread-Prioritäten (SetPriorityClass, SetThreadPriority, ...)
- Thread-Synchronisation (CriticalSections, InterLockedExchangeXXX, ...)
- Thread-Synchronisation mit Kernelobjekten (neu in 2.2) (WaitForXXX, CreateEvent, SetEvent)
- Das Thread Objekt der VCL
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 public 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' ;
{$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.
Delete - Mi 02.04.08 11:34
Ein neue überarbeitet und erweiterte Version ist erschienen.
Neu sind die Kapitel
- Der Stack eines Threads - neu in Version vom 2008-04-02
- Threadpools - neu in Version vom 2008-04-02
- Pseudo-Threads(Fibers) - neu in Version vom 2008-04-02
Download des Tutorials und zugehörigen Demos im ersten Beitrag.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!