Warum nimmst du nicht die TThread-Vorlage von Delphi? Dann kuckst du dir im Demo-Ordner das Threading-Demo an und dann sollte das klappen.
Aber hier mal eine kleine Demo, wenn du kein TThread-Objekt benutzen willst:
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:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; ListBox1: TListBox; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormDestroy(Sender: TObject); private
public end;
var Form1 : TForm1; bRunning : Boolean = FALSE; hThread : Cardinal; cs : RTL_CRITICAL_SECTION;
implementation
{$R *.dfm}
function FillLBThread(p: Pointer): Integer; var i : Integer; begin result := 0; i := 0; while bRunning = TRUE do begin EnterCriticalSection(cs); try Form1.Listbox1.Items.Add((IntToStr(i))); Form1.Label1.Caption := IntToStr(i); finally LeaveCriticalSection(cs); end; Inc(i); if i = 1000000 then EndThread(0); sleep(50); end; EndThread(0); end;
procedure TForm1.Button1Click(Sender: TObject); var ThreadID : LongWord; begin ThreadID := 1; hThread := BeginThread(nil, 0, @FillLBThread, nil, 0, ThreadID); if hThread <> 0 then bRunning := TRUE; end;
procedure TForm1.Button2Click(Sender: TObject); begin bRunning := FALSE; end;
procedure TForm1.FormDestroy(Sender: TObject); begin if bRunning = TRUE then begin bRunning := FALSE; TerminateThread(hThread, 0); end; end;
initialization InitializeCriticalSection(cs);
finalization DeleteCriticalSection(cs);
end. |
OK, das ist jetzt die dritte und wahrscheinlich letzte, da korrekte Version mit den CriticalSections. Im Code sind zwei Varianten: einmal die auskommentierte VCL Version mit der Unit SyncObjs, welche über 100 KB zur Exe beisteuert und einmal die verwendete reine Win32API-Version.
Die CriticalSections sind nötig, da im Thread auf globale Variablen bzw. Objekte zugegriffen wird und es gefährlich ist, wenn mehrer Threads gleichzeitig darauf zugreifen. CriticalSections sind dann wichtig, wenn mehrere Threads lesend und schreibend auf eine Variable zu greifen, um die Konsistenz zu gewährleisten.
Achtung der direkte API-Aufruf CreateThread sollte vermieden werden. Aus der Delphi-Hilfe:
| Zitat: |
BeginThread encapsulates the Win32 CreateThread API call, but unlike CreateThread, it sets the global IsMultiThread variable, thereby making the heap thread-safe.
|