Autor Beitrag
kalypso1977
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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:

ausblenden volle Höhe 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:
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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  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

    //animiertes Gif laden und laufen lassen im HauptThread
    FGifImage := TGIFImage.Create;
    FGifImage.LoadFromFile(ExtractFilePath(ParamStr(0))+'loading.gif');
    Image1.Picture.Assign(FGifImage);

    //Rechenintensive Schleife in Thread verlagern und warten bis sich dieser
    //beendet, in dieser Zeit soll das animierte Gif und die
    //HauptForm weiter sauber reagieren...
    hThread := BeginThread(nil0, @Thread, nil0, ThreadID);

    repeat
      WaitResult := MsgWaitForMultipleObjects(1, hThread, False, INFINITE, QS_ALLINPUT);
      if WaitResult = WAIT_OBJECT_0 + 1 then begin
        while PeekMessage(Msg, Form1.Handle, 00, 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 user profile iconGausi: Code- durch Delphi-Tags ersetzt
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 20.10.09 13:49 
Moin und :welcome: im Forum!

Ich halte deinen APM-Schleifen-Ansatz für nicht so gut. :nixweiss: Schau mal hier, vielleicht ist das das, was du suchst. :les: :think: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
kalypso1977 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 20.10.09 14:29 
Moin!

user profile iconkalypso1977 hat folgendes geschrieben Zum zitierten Posting springen:
Das Beispiel ist prinzipiell gut, passt aber nicht auf meine Anforderung.
Was hast du erwartet, c&p? :zwinker: 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.
:idea: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
kalypso1977 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 20.10.09 15:24 
Danke für deine Hilfe!

Habs jetzt hinbekommen - ging doch :lol:

Prima!
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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.