Autor Beitrag
David
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Mo 09.02.04 18:50 
Hallo,
ich habe ein kleines Probem. Ich versuche mich grad in Threads einzuarbeiten und leider stürzt mein Mini Programm immer ab.

Hier der Code:
ausblenden 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:
var
  ThreadID : THandle; 
  ThreadH : THandle;
  ThreadID2 : THandle;
  ThreadH2 : THandle;

procedure threadtest (Edit : TEdit); stdcall;
var a: integer;
begin
  for a:=0 to 5000 do
//    Edit.text := IntToStr(a);
    ShowMessage('Thread 1 fertig!');
    ThreadH:=0;
end;

procedure threadtest2 (Edit : TEdit); stdcall;
var a: integer;
begin
  for a:=0 to 1000 do
//    Edit.text:=IntToStr(a);
    ShowMessage('Thread 2 fertig!');
    ThreadH2:=0;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  ThreadH:=CreateThread(nil,0,@threadtest,Edit1,0,ThreadID);
  ThreadH2:=CreateThread(nil,0,@threadtest2,Edit1,0,ThreadID2);
end;


Mit einem Thread geht es, aber bei 2 kann ich es vergessen.

Jemand ne Ahnung was ich falsch gemacht habe?

Moderiert von user profile iconPeter Lustig: Code- durch Delphi-Tags ersetzt
patrick
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 1481

WIN2k, WIN XP
D6 Personal, D2005 PE
BeitragVerfasst: Mo 09.02.04 19:02 
irgendwie erstelle ich theads ganz anders :?

schau dir am besten mal das thread-tut von Luckie an:
www.luckie-online.de...threads_tutorial.pdf

so mach ich das immer:
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:
unit thread_unti1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TmyTThread = class(TThread)
   public
   procedure Execute; override;
end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public

  end;

var
  myt1,myt2:TmyTThread;
implementation

{$R *.dfm}

procedure TmyTThread.Execute;
var i:integer;
begin
///eine aktion
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  myt1.Create(false);
  myt2.Create(false);
end;


end.

_________________
Patrick
im zweifelsfall immer das richtige tun!!!


Zuletzt bearbeitet von patrick am Mo 09.02.04 19:08, insgesamt 1-mal bearbeitet
David Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Mo 09.02.04 19:05 
Hallo patrick,
das Tutorial ist mir bekannt, es geht aber in eine etwas andere Richtung. Um Threads zu erstellen gibt es schon mehrere Möglichkeiten, diese ist jedoch für meine Situation die Beste.
Ich verstehe nur halt nicht, wieso er beim 2. erstellten Thread abstürtzt und beim 1. nicht.
MSCH
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: Mo 09.02.04 19:25 
schätze mal, dass deine Initialisierung etwas daneben läuft. Deine Treads laufen erstmal unendlich, rufen unendlich eine Schleife auf und geben eine Dialog aus. Ob diese Funktion Threadsicher ist, wage ich zu bezweifeln und den Thread via :=0 zu terminieren (?) geht auch nicht. Da solltest du schon CloseHandle benutzen. Schau dir mal die Erläuterungen im SDK dazu an.
Das der erste funktioniert, ist Zufall (?).

grez
msch

_________________
ist das politisch, wenn ich linksdrehenden Joghurt haben möchte?
David Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Mo 09.02.04 19:36 
ok, danke Euch beiden. Ich denke, ich bekomme das jetzt hin!
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 09.02.04 20:04 
Kennen schon, aber nicht gelesen oder:
Thread-Tutorial hat folgendes geschrieben:

Zu beachten ist allerdings noch folgendes: Benutzt man BeginThread als Wrapper für die API-Funktion CreateThread,
so darf man nicht die Aufrufkonvetion stdcall für die Thread-Funktion benutzen. Grund: BeginThread benutzt eine
"Thread-Wrapper"-Funktion anstatt des wirklichen Einsprungspunktes. Diese Funktion ist als stdcall definiert, sie verschiebt
die Parameter auf den Stack und ruft dann die eigene Thread-Funktion auf.

[..]

In einem Delphi-Programm sollten sie nie die Funktion CreateThread direkt aufrufen. Benutzen sie stattdessen die
Funktion BeginThread. Grund: BeginThread kapselt zwar nur die API-Funktion CreateThread, setzt aber zusätzlich
noch die globale Variable IsMultiThread und macht somit den Heap thread-sicher.

Die Thread-Funktion sieht auch anders aus:
ausblenden Delphi-Quelltext
1:
type TThreadFunc = function(Parameter: Pointer): Integer;					

Aber das eigentliche Problem dürfte die Übergabe des Edits als Thread-Parameter sein. Wie man Parameter an Threads übergibt kannst du in den Demos zu meinem Tutorial sehen. Übergib einen Zeiger auf einen Record.
Und nimm mal statt ShowMessage, Messagebox (die API-Version). Die VCL ist nämlich nicht thread-safe.
Und was deine aukommentierte Edit-Zeile angeht, mach dich mal in meinem Tutorial über CriticalSections schlau.
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mo 09.02.04 20:53 
Also was den Parameter betrifft so ist der obige Code durchaus korrekt, schließlich sind in Delphi ja alle Objekte nur Zeiger, also entspricht das übergebene TEdit-Objekt durchaus dem Pointer-Parameter von TThreadFunc. Die Prozeduren sind zwar als stdcall deklariert, aber es sind eben Prozeduren und keine Funktionen wie TThreadFunc (aber das allein ist noch kein schwerwiegendes Problem).

Ich seh das Problem auch bei den VCL-Zugriffen und zwar sowohl bei ShowMessage als auch bei den Zugriffen auf das Edit. Und VCL-Zugriffe würde ich generell sicherheitshalber eher über Synchronize machen als mit CriticalSections, da mit Synchronize der Code im primären Thread ausgeführt wird, während man per CriticalSection zwar seine eigenen Zugriffe auf ein VCL-Control synchronisieren kann, aber was die VCL im Hintergrund macht kann man nicht kontrollieren...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!