Autor |
Beitrag |
kalypso1977
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 20.10.09 13:30
Hallo zusammen!
Ich habe ein kleines Demoprogramm geschrieben welches eine rechentintensive Schleife in einem Nebenthread abarbeitet und eine Listbox mit Werten befüllt.
Auf das Fertigstellen der Schleifenabarbeitung im HauptThread (MainForm) soll mit einem MsgWaitForMultipleObjects gewartet werden. Geht auch soweit, aber während der Abarbeitung der rechenintensiven Schleife im NebenThread, soll ein animiertes Gif (loading.gif) weiterlaufen bzw. die GUI des HauptThreads von dieser rechenintensiven Abarbeitung nicht beeinträchtigt werden. Leider bekomme ich das einfach nicht hin. Auch das tolle Thread Tutorial von Michael Puff hat mir nicht wirklich weitergeholfen, von einer Recherche in Google ganz abgesehen.
Kann mir jemand helfen? Ich wäre euch mehr als dankbar. Mein Ziel ist es, einfach gewisse rechenintensive Abläufe in einem Thread zu verlagern die aber die weiterarbeit im Hauptthread solange "stoppen" bis sie sich terminiert haben bzw. abgearbeitet sind...
Anbei der aktuelle Beispiel-Code:
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:
| unit main;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, GIFImage, ExtCtrls, StdCtrls, Buttons, ShellApi;
type TForm1 = class(TForm) Button1: TButton; Image1: TImage; Button2: TButton; ListBox1: TListBox; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private public end;
var Form1: TForm1;
implementation
{$R *.dfm}
function Thread(p: Pointer): Integer; var i : integer; begin for i := 0 to 999 do begin Form1.ListBox1.Items.Add(IntToStr(i)); sleep(10); end; end;
procedure TForm1.Button1Click(Sender: TObject); var hThread : THandle; ThreadID : Cardinal; WaitResult : DWORD; Msg : TMsg; FGifImage:TGIFImage;
begin
try
FGifImage := TGIFImage.Create; FGifImage.LoadFromFile(ExtractFilePath(ParamStr(0))+'loading.gif'); Image1.Picture.Assign(FGifImage);
hThread := BeginThread(nil, 0, @Thread, nil, 0, ThreadID);
repeat WaitResult := MsgWaitForMultipleObjects(1, hThread, False, INFINITE, QS_ALLINPUT); if WaitResult = WAIT_OBJECT_0 + 1 then begin while PeekMessage(Msg, Form1.Handle, 0, 0, PM_REMOVE) do begin TranslateMessage(Msg); DispatchMessage(Msg); end; end; until WaitResult = WAIT_OBJECT_0;
finally FreeAndNil(FGifImage); end; end;
procedure TForm1.Button2Click(Sender: TObject); begin Application.Terminate; end;
end. |
Moderiert von Gausi: Code- durch Delphi-Tags ersetzt
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 20.10.09 13:49
Moin und  im Forum!
Ich halte deinen APM-Schleifen-Ansatz für nicht so gut. Schau mal hier, vielleicht ist das das, was du suchst.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
kalypso1977 
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 20.10.09 14:23
Hi!
Danke für die schnelle Antwort. Ich habe dein Beispiel mal ausprobiert.
1) Allerdings möchte ich schon, wie in meinem Code, "nach" der Abarbeitung des Threads einfach mit dem MainThread (ButtonCode) weitermachen. Das geht schon mal nicht in deinem Bespiel. Klickt man auf den Startbutton wird dieser vollständig ausgeführt und beendet.
2) Desweiteren wird im TimerThread eine Schleife durchlaufen die entweder terminiert durch einen Timeout oder durch die Anzahl an steps (Steps wird mit Decrease heruntergezählt). Der "Code" innerhalb der Schleife wird also mehrmals ausgeführt. Das möchte ich ja auch nicht. Mein Threadcode soll einmal ausgeführt werden. Er ist halt nur rechenintensiv! Die Schleife in meinem Nebenthread die eine Listbox mit Werten füllt war nur ein Beispiel dafür...
Das Beispiel ist prinzipiell gut, passt aber nicht auf meine Anforderung.
LEIDER!!
Hast du noch eine andere Idee? Bzw. habt Ihr noch eine andere Idee...??
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 20.10.09 14:29
Moin!
kalypso1977 hat folgendes geschrieben : | Das Beispiel ist prinzipiell gut, passt aber nicht auf meine Anforderung. |
Was hast du erwartet, c&p?  Der Ansatz ist das Entscheidende: - Du hast einen Button, der die Aktion startet (mal als Beispiel)
- nach dem Klick auf den Button deaktivierst du ihn, damit man den Thread nicht nochmal starten kann; dann startest du den Worker-Thread
- Wenn dieser Terminiert, schickt er dir eine Nachricht, dass er fertig ist (OnTerminate im VCL-Thread-Modell, siehe Lib-Beitrag)
- In diesem Thread-Fertig-Handler führst du die Aktionen aus, die du jetzt nach deiner APM-Schleife hast.
- Abschließend könnte man im Handler den Button wieder aktivieren, dann kann man das ganze nochmal machen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
kalypso1977 
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 20.10.09 15:24
Danke für deine Hilfe!
Habs jetzt hinbekommen - ging doch
Prima!
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 27.10.09 14:58
Der Source im Thread sollte nicht auf die VCL zugreifen ... zumindest nicht unsynchronisiert.
Und dann deaktiviert man bitte schön das automatische Update ... sonst ist das lahm ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|