![]() |
Fragen zu Threads: Prozedur als Thread ausführen
Hallo,
ich würde gerne eine Prozedur als Thread ausführen, damit die Anwendung selbst weiterhin reagiert. Habe mir bereits das ![]() |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Hallo,
deine Frage ist etwas vage: "Ich habe ein Problem, kann mir jemand helfen" spiegelt ungefähr den Inhalt deines Problems... Also was genau willst du denn in dem Thread machen? Gruß, |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Hallo,
dachte der Titel des Themas würde das klar machen: Wenn der User auf einen Button klickt, wird eine Prozedur ausgeführt. Diese Prozedur benötigt viel Zeit. Während des Vorgangs, reagiert aber die Hauptanwendung nicht mehr. Daher will ich diese Prozedur in einem extra Thread ausführen. Quasi: User klickt Button -> Thread "DoProcess" erstellen -> Thread Auzführen (hier wird die eigentliche Prozedur ausgeführt) -> Wenn Thread Fertig -> Thread Ende. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Hallo,
zum Thema Threads einfach mal bei ![]() MfG wZ |
Re: Fragen zu Threads: Prozedur als Thread ausführen
wo liegt den das problem? weil eigentlich zielt luckies tut genau darauf ab! wo kommst du nicht weiter?
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
Wenn du eine konkrete Frage hast zu meinem Tutorial, was du nicht dabei verstanden hast, dann solltest du die auch stellen. Mit einem " jedoch hilft es mir auch nicht viel weiter" kann dir hier auch niemand weiterhelfen.
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
hi whissi,
versuchs mal so:
Delphi-Quellcode:
procedure blub;
var i: integer; begin for i := 0 to 1000000 do Form1.ListBox1.Items.Add(IntToStr(i)); end; procedure TForm1.Button1Click(Sender: TObject); var id: cardinal; begin createthread(nil, 0, @blub, nil, 0, id); end; |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Und genau so bitte nicht!
Erstmal sollte man niemals direkt ![]() Zitat:
Zitat:
Delphi-Quellcode:
Sollte zwar auch gut gehen, kann aber auch böse ins Auge gegehen. Stichwort an dieser Stelle
Form1.ListBox1.Items.Add(IntToStr(i));
![]() ![]() |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Ich blicke es nicht :/
Das PDF als solches ist verständlich. Jedoch hilft es mir nicht weiter. Ich weiß eben nicht, wie ich nun hingehe und einen Thread aufrufe, der eine Funktion/Prozedur abarbeitet. Ich will eigentlich nur folgendes: Durch eine Aktion auf dem Hauptformular (z.B. Button-Click), soll eine Prozedur in einem eigenen Thread ausgeführt werden (nur als Info: die auszuführende Prozedur erstellt eine HASH-Summe) und wenn die Prozedur durchgelaufen ist (=Hashsumme erstellt wurde), soll sich der Thread wieder beenden und das Hauptform wieder aktiv werden. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
wenn du die hauptform derweil deaktivierst, kannst du dir den thread auch sparen, denn dann ist er total überflüssig!
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
Mir geht's um folgendes:
Wenn ich die HASH-Summe erstellen lasse, reagiert das Programm in der Zeit nicht. Daher will ich einen zusätzlichen "Prozess" (=Thread) starten, der dies macht. Die Formulierung "deaktivieren" habe ich genutzt, weil ich nicht will, dass während der Thread, welche die HASH-Summe erstellt aktiv ist, der User das Programm munter weiter bedienen kann... |
Re: Fragen zu Threads: Prozedur als Thread ausführen
:arrow: Wenn du das Hauptform während der Threadausführung nicht brauchst, brauchst du auch keinen Thread (nur am Rande)
Aber zu deinem Problem: Ich benutze immer Das Objekt ![]() In die Klassenmethode TThread.Execute kommt das rein, was der Thread machen soll Alle Zugriffe auf die VCL müssen in seperaten Klassenfunktoionen erfolgen, welche mit ![]() P.S. Wenn du regelmäßig Application.ProcessMessages aufrufst, reagiert dein Programm auch ... |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Zitat:
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
Eine Frage zu "Synchronize":
Ich verstehe nicht ganz wann ich es aufrufen muss. Delphi sagt: Zitat:
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
Moin Whissi,
schau Dir das Beispiel doch noch mal genau an. Die Methode die mit Synchronize aufgerufen wird ist eine Methode des Threads. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Guten Abend,
Danke für die Antworten. Noch komme ich aber nicht weiter. Ich habe nun folgendes gemacht: Das Hauptformular erstellt ein "frmCheck". Das Fenster bekommt "ShowModal" Status und nach 1sek werden die Prozeduren abgearbeitet. Unter anderem rufe ich folgendes auf:
Code:
("mCheck_Thread" ist die PAS-Datei, die den "Thread-Code" enthält (erstellt Mittels Delphi (Datei -> Neu...))
mCheck_Thread.TMyThread.Create(false);
Die Prozedur wird auch abgearbeitet, jedoch beim Beenden steigt das Programm mit einer Zugriffsverletzung aus. Delphi makiert dann die Zeile "Timer1.Enabled := false;" der Prozedur "TfrmCheck.pd_CheckAll". Den Thread synchronisiere ich Mittels "Synchronize(frmCheck.CheckAll);". |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Dazu ein paar Fragen:
- Was heisst nach 1sek? Per Timer? - Wenn ja: o Wann wird der ausgelöst? Im OnCreate oder OnShow? o Wird der Thread innerhalb der Timerprozedur ausgelöst? o Wenn ja: Timer1.Enabled := false; vor dem erstellen des Threads setzen. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Ja, per Timer.
User klick auf frmMain einen Button und frmCheck wird erstellt. Im FormCreate Ereignis wird der Timer auf Enabled gesetzt. Im OnTimer Ereignis wird zu erst der Timer deaktiviert und dann eine andere Prozedur ausgeführt und schließlich die Prozedur aufgerufen, die den Thread starten soll. Also wird der Timer VOR der Ausführung des Threads deaktiviert. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Achso, ist Timer1 dann einer anderer Timer? Weil du ihn in pd_CheckAll ja nochmal deaktivierst, oder ist das die betreffende Timerprozedur?
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
Form startet Timer.
Timer ruft CheckAll auf. Check all ruft alle Sub-Routinen auf - u.a. die des Threads. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Hmmm... dann fällt mir nur noch eins ein:
- Wie sieht es mit FreeOnTerminate aus? Ist das beim Thread auf true, damit der sich am Ende freigibt? - Du erstellst den Thread direkt. Ich weis nicht, ob das Probleme macht, aber evtl. solltest du eine Variable im TfrmCheck definieren, der der Thread zugewiesen wird.
Delphi-Quellcode:
HashThread := mCheck_Thread.TMyThread.Create(false);
|
Re: Fragen zu Threads: Prozedur als Thread ausführen
Hallo Whissi,
also ohne deinen Quellcode zu sehen, kann man schlecht sagen wo der Fehler liegt. Ich weiß auch nicht welche Aufgabe der Timer in deinem Projekt hat. Ich will dir aber anhand eines kleinen Beispiels zeigen, wie du einen Thread in deinem Projekt einsetzen kannst.
Delphi-Quellcode:
Beim Klick auf den Button wird dieser deaktiviert und ein neuer Thread wird erstellt.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } procedure OnThreadTerminate(Sender: TObject); public { Public-Deklarationen } end; TMyThread = class(TThread) public procedure Execute; override; end; var Form1: TForm1; implementation {$R *.dfm} {--------------------------------------------------------------------------------------------------} procedure TMyThread.Execute; begin Sleep(2000); end; {--------------------------------------------------------------------------------------------------} procedure TForm1.OnThreadTerminate(Sender: TObject); begin Screen.Cursor := crDefault; Button1.Enabled := True; end; {--------------------------------------------------------------------------------------------------} procedure TForm1.Button1Click(Sender: TObject); begin Screen.Cursor := crHourGlass; Button1.Enabled := False; with TMyThread.Create(True) do begin FreeOnTerminate := True; OnTerminate := OnThreadTerminate; Resume; end; end; {--------------------------------------------------------------------------------------------------} end. Beim erstellen wird der Constructor Create mit dem Wert True aufgerufen. So wird der Thread zwar erstellt aber noch nicht ausgeführt. Jetzt können einige Werte gesetzt werden. Zum Beispiel FreeOnTerminate. Damit du dich nicht selber um die Klassenspeicherverwaltung kümmern musst. Außerdem kannst du dort auch ein Ereignis setzten, das ausgeführt wird, wenn der Thread mit seiner Arbeit fertig ist. Erst der Aufruf von Resume führt dann den Thread aus. Ist der Thread beendet, wird das Ereignis OnThreadTerminate aufgerufen und der Button wird wieder aktiviert. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Hallo,
vielen Dank!!! Nach etwas herumspielen mit deinem Code-Beispiel konnte ich es 1:1 auf mein Projekt übertragen und habe es sogar verstanden (hoffe ich zumindest *G*). Jedenfalls macht das, was das Programm macht, Sinn ;-) Danke noch einmal! |
Re: Fragen zu Threads: Prozedur als Thread ausführen
ARGHS!
Das war wohl doch zu Vorschnell. In meinem Test-Projekt hat's soweit geklappt. Dort habe ich eben eine globale Variable im Wert verändert sowie Objekte des Formulars sichtbar/unsichtbar gemacht. In dem richtigen Projekt, bekomme ich nun Zugriffsverletzungen. Dabei habe ich deinen Code 1:1 reinkopiert. |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Update:
Ich kann die Zugriffsverletzung nun klar festlegen: Ich lass in dem Thread der Variable "HASH", welche sich auf dem Formular "frmCheck" befindet, die ermittelte MD5-Hash übergeben. Beim Schreiben in diese Variable, steigt er aus. Dies ist mir jedoch unerklärlich, da ich mit der Variable zur Zeit weiter nichts mache - es sollte also kein Zugriff von anderen Forms auf die Variable existieren. Imho muss ich hier nun synchronisieren, nur wie bzw. womit? |
Re: Fragen zu Threads: Prozedur als Thread ausführen
Zitat:
Beispiel VCL Komponenten und Threads: (brauchst einen Button (Button1) und ein Textfeld (Edit1).
Delphi-Quellcode:
Ein Beispiel wenn du mehrere Threads hast, die die selbe Variable zum Lesen und Schreiben benutzen:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; TMyThread = class(TThread) private FEdit: TEdit; FHash: String; procedure Sync; protected procedure Execute; override; public constructor Create(Edit: TEdit; Hash: String); end; var Form1: TForm1; implementation {$R *.dfm} {--------------------------------------------------------------------------------------------------} constructor TMyThread.Create(Edit: TEdit; Hash: String); begin inherited Create(True); FEdit := Edit; FHash := Hash; end; {--------------------------------------------------------------------------------------------------} procedure TMyThread.Sync; begin FEdit.Text := FHash; end; {--------------------------------------------------------------------------------------------------} procedure TMyThread.Execute; begin Synchronize(Sync); end; {--------------------------------------------------------------------------------------------------} procedure TForm1.Button1Click(Sender: TObject); begin with TMyThread.Create(Edit1, 'ABC123') do begin FreeOnTerminate := True; Resume; end; end; {--------------------------------------------------------------------------------------------------} end.
Delphi-Quellcode:
Das Programm hat eigentlich keinen Auftrag, es soll dir nur zeigen wie du die Delphi Komponente TMultiReadExclusiveWriteSynchronizer einsetzen kannst.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) private { Private-Deklarationen } public { Public-Deklarationen } end; TReadThread = class(TThread) protected procedure Execute; override; end; TWriteThread = class(TThread) protected procedure Execute; override; end; var Form1: TForm1; implementation {$R *.dfm} var Safe: TMultiReadExclusiveWriteSynchronizer; procedure TReadThread.Execute; begin with Safe do begin BeginRead; // hier kannst du sicher von deiner Variablen lesen EndRead; end; end; procedure TWriteThread.Execute; begin with Safe do begin BeginWrite; // hier kannst du sicher in deine Variablen schreiben EndWrite; end; end; initialization Safe := TMultiReadExclusiveWriteSynchronizer.Create; finalization if Assigned(Safe) then Safe.Free; end. Beim Lesen: BeginRead, EndRead Beim Schreiben: BeginWrite, EndWrite Der Fehler der bei dir Auftritt, hat aber wohl einen anderen Grund. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz