Autor Beitrag
Steve1024
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Do 15.09.05 14:27 
Hi an alle,

ich hab mir ein kleines Prog geschrieben (besser DLL Dateien), welche eine volle Interprozesskommunikation ermöglichen (wie z.B. TCP nur halt lokal ohne netzwerk usw.).

Ich hab da jetzt folgendes Problem:

{Client}
Ich erstelle ein Thread in dem Constructor eines Objects (nur zum empfangen von Daten). Sende dem ServiceThread das ich mich anmelden möchte und warte auf antwort.... und warte.... und warte.... (ServerThread sendet aber)

Gut... also Problem ist das Warten... Ich hab dabei dann mal den Debugger laufen lassen und festgestellt, dass der Thread gar nicht ausgeführt wird... D.h. wird er schon... sobald ich aus dem Create drausen bin.... D.h. wenn ich im Form constructor das Object erstelle... wird der Thread erst dann ausgeführt, wenn ich da auch wieder draußen bin...

Für Consolen-Anwendung ist das also z.B völlig ungeeignet, denn wenn ich draußen bin... läufts ja ned mehr...

Weiß jemand, wie ich den Thread sofort nach dem erstellen ausführen kann... so eine art API-Funktion.... Dass also in diesem beispiel er nicht ewig wartet.... sondern auch in der lage ist eine antwort zu senden??
MrSaint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1033
Erhaltene Danke: 1

WinXP Pro SP2
Delphi 6 Prof.
BeitragVerfasst: Fr 16.09.05 08:17 
Wie sieht dein Thread denn aus? Abgeleitete Klasse von TThread oder einfach Funktion, oder... ? Und wie startest du den Thread? Meiner Meinung nach müsste der auch sofort starten...


MrSaint

_________________
"people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 16.09.05 08:43 
Ja, der ist von TThread abgeleitet.
Dazu wird der über Create gestartet (Suspend = FALSE)
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 16.09.05 09:24 
Hallo!

Sobald du den Thread erstellt hast, ist es eine Sache vom Betriebssystem, diesem Rechenzeit zuzuweisen. Das kannst du nur über die Threadpriority beeinflussen. Wann der nun aber den einen oder anderen Breakpoint erreicht, ist immer noch ungewiss.

Bei Konsolenanwendungen musst du doch irgendwie dann auf Input warten. Wenn die Konsolenanwendung sich vorher beendet, scheint der Input ja dann nicht nötig zu sein.

Cu,
Udontknow
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 16.09.05 11:33 
Sagen wir mal so... meine Consolenanwendung kovertiert eine Datei in irgendwas....
Der Thread soll die Datei kovertieren und eine Schleife überwacht den Status... Welche Datei kovertiert werden soll, wird als Parameter übergeben (somit ist keine Eingabe von nöten).

Sobald keine eingabe von nöten ist, und die Schleife durchläuft, wird der Thread nicht gestartet...
D.h. der Thread wird erstellt... die Schleife kann auch den Status abfragen, welcher aber immer auf 0 bleibt, weil die Exceute Procedure nur in einer Pause aufgerufen wird...

Denkst du, dass das Problem beseitigt ist, wenn ich die Priorität von Idle auf ??was?? stelle? Denn bei Realtime, reagiert dann mein ganzes System nicht mehr, wenn ich das mache... hatte ich mal ausprobiert... deswegen habe ich das da mal sein lassen... *g*
MrSaint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1033
Erhaltene Danke: 1

WinXP Pro SP2
Delphi 6 Prof.
BeitragVerfasst: Fr 16.09.05 11:47 
Vielleicht solltest du es auf Normal setzen! Bei Idle ist ja klar dass es nicht funktioniert, da macht der thread ja nur was, wenn der Rechner grad so gut wie nix anderes zu tun hat! Die Priority von deinem Thread sollte midnestens so hoch sein wie von deinem restlichen Programm...



MrSaint

_________________
"people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 16.09.05 11:52 
OK, werd ich mal ausprobieren und melde mich dann wieder...

Danke auf jeden fall jetzt schon..
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 16.09.05 13:47 
user profile iconSteve1024 hat folgendes geschrieben:
Sobald keine eingabe von nöten ist, und die Schleife durchläuft, wird der Thread nicht gestartet...
D.h. der Thread wird erstellt... die Schleife kann auch den Status abfragen, welcher aber immer auf 0 bleibt, weil die Exceute Procedure nur in einer Pause aufgerufen wird...


Da komme ich nicht mehr mit. Was für eine Pause? Vielleicht zeigst du mal ein wenig Code. Probiere es in der Schleife auch ruhig mal mit Sleep.

Cu,
Udontknow
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 16.09.05 14:36 
Also:
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:
program Test

  TAThread = class(TThread)
  protected
    procedure Execute; override;
  public
    Status : String;
  end;

  procedure TAThread.Exceute;
  var Q : Integer;
  Begin
    Q := 0;
    while Q < 4096 do
    begin
      Status := 'Wird ausgeführt';
      inc(Q); Slepp(100);
    end;
    Status := 'Beendet';
  end;

var Q : TAThread;
    tmpMsg : TMsg;
begin
  Q := TThread.Create(FALSE)
  try
    while Q.Status <> 'Beendet' do
    Begin
      writeln(Q.Status); // bleibt immer leer
      PeekMessage(tmpMSg,0,0,0,PM_REMOVE);
    end;
  finally
    Q.Free;
  end;
  Readln;
end;


So ungeführ würde mein Prog aussehen...
Vielleicht kann man mir da jetzt ja besser helfen...
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 16.09.05 15:54 
Hallo!

1. Hast du diesen Code mal getestet, den du da hingeschrieben hast? Der strotzt nur so vor Fehlern, compilierbar ist´s nicht.

2. Wenn du 4096 mal 100 ms wartest, sind das 496 Sekunden, also über 8 Minuten. Hast du wirklich so lange gewartet?

3. Wenn Q.Status endlich "Beendet" enthält, gibst du es nicht aus, das könnte dich auch zu einer falschen Annahme geführt haben.

4. Beschäftige dich mal intensivst mit Synchronisation von Threads. Einfach so Elemente wie Strings in verschiedenen Threads abzugreifen ist nämlich nicht gut, das führt zu bösen Effekten wie AV usw.


Hier mal der halbwegs überarbeitete 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:
program Test;

{$APPTYPE CONSOLE}

uses Windows,Classes,SysUtils;

type TAThread = class(TThread)
  protected  
    procedure Execute; override;  
  public  
    Status : String;  
  end;

  procedure TAThread.Execute;
  var Q : Integer;
  Begin
    Q := 0;
    while Q < 10 do
    begin
      Status := 'Wird ausgeführt';
      inc(Q);
      Sleep(1000);
    end;
    Status := 'Hey, der Thread ist beendet!';
  end;


var Q : TAThread;
var WaitResult:Integer;
begin
  Q := TAThread.Create(FALSE);
  try
    Repeat
      WaitResult:=WaitForSingleObject(Q.Handle,1000);
      if WaitResult<>0 then
        writeln('Thread ist noch nicht beendet.');
    until WaitResult=0;

    WriteLn(Q.Status);
  finally
    Q.Free;
  end;
  Readln;
end.


Cu,
Udontknow
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Fr 16.09.05 19:21 
Ich hab ja deswegen geschrieben, dass er so ungefähr aussieht... (hab das schnell aus meinem Kopf getippt gehabt)....

Also nun der richtige Quellcode... vielleicht sagt der dir mehr..

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:
unit TestThread;

interface

uses Classes, Windows, Messages, SysUtils;

  TSTestObject= class
    constructor Create;
    destructor Destroy; override;
  private
    FReadThread  : TThread;
    FThreadID : Cardinal;
  published
    property ThreadID : Cardinal read FThreadID;
  end;

implementation

type
  TSTestThread= class(TThread)
    destructor Destroy; override;
  protected
    procedure Execute; override;
  end;

  destructor TSTestThread.Destroy;
  Begin
    PostThreadMessage(ThreadID,WM_DESTROY,0,0);
    inherited;
  end;

  // ========== Protected Methods ==========

  procedure TSTestThread.Execute;
  var vMsg : TMsg;
  Begin
    while not Terminated do
    Begin
      IF GetMessage(vMsg,0,0,0THEN
        case vMsg.message of
          WM_DESTROY : Terminate;
        ELSE
          {...}
          // z.B: MessageBox(0,PChar(IntToStr(vMsg.message)),nil,0);
        end;
    end;
  end;

// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  constructor TSTestObject.Create;
  Begin
    inherited;
    FReadThread := TSTestThread.Create(FALSE);
    FThreadID := FReadThread.ThreadID;
    {...}
  end;

  destructor TSTestObject.Destroy;
  Begin
    FReadThread.Free;
    inherited;
  end;

// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

end.


Wenn ich jetzt das Object erstelle und über PostThreadMessage eine nachricht schicke... bekomme ich diese nicht...

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  procedure Test;
  var Q : TSTestObject;
  Begin
    Q := TSTestObject.Create;
    try
      IF not PostThreadMessage(Q.ThreadID,WM_USER,0,0THEN
        MessageBox(0,'Error sending',nil,0);
    finally
      Q.Free;
    end;
  end;


Ich denke mal, dass das bei dir auch so sein könnte, oder??
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 16.09.05 19:57 
Also hast du letztendlich überhaupt gar kein Problem mit Threads, sondern mit Botschaftsbehandlung. :roll:

Tja, da bin ich auch nicht so fit.

Cu,
Udontknow
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: So 18.09.05 17:22 
Nein.

es ist so, erstelle ich den Thread und sende erst später die Message, dann funktioniert es.

Also das heisst, dass ich PostThreadMessage über einen Timer laufen lasse (oder nach einer Eingabe), dann funktioniert es problemlos.

Es ist nur, wenn ich in der Procedure gleich nach dem Erstellen eine MessageSende.

Ich habe auch mit dem Debugger festgestellt, dass eben der Thread erst nach dem Ende der Procedure ausgeführt wird. Also, d.h. ich könnte machen, was ich will (egal ob jetzt mit Messages oder nicht), er wird erst nach der Procedure ausgeführt... oder???
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: So 18.09.05 19:40 
Zitat:
Ich habe auch mit dem Debugger festgestellt, dass eben der Thread erst nach dem Ende der Procedure ausgeführt wird. Also, d.h. ich könnte machen, was ich will (egal ob jetzt mit Messages oder nicht), er wird erst nach der Procedure ausgeführt... oder???


Ich habe dir doch schon gesagt, daß es völlig unbestimmbar ist, wann der Thread das erste Mal Rechenzeit von Windows bekommt. Du hast sehr wohl nur ein Problem im Bereich "Botschaftsbehandlung".

Folgendes über PostThreadMessage:
Zitat:
The thread to which the message is posted must have created a message queue, or else the call to PostThreadMessage fails. Use one of the following methods to handle this situation:

· Call PostThreadMessage. If it fails, call the Sleep function and call PostThreadMessage again. Repeat until PostThreadMessage succeeds.


Cu,
Udontknow
Steve1024 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 141

Windows 2K, XP, 7 & Server 2003 - 2008; Linux (Ubuntu, Fedora)
D7, D05, D06, D09, DXE
BeitragVerfasst: Di 20.09.05 11:56 
Ok, ich werde das mal testten... danke auf jeden fall...