Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Mutithreading: Konsolenausgabe hakt (https://www.delphipraxis.net/192279-mutithreading-konsolenausgabe-hakt.html)

iphi 5. Apr 2017 09:42

Mutithreading: Konsolenausgabe hakt
 
Hallo,

ich habe ein kleines Delphi7-Programm geschrieben, in welchem ein separater Thread mit Windows.ReadFile() ständig einen seriellen COM-Port scannt und, wenn Daten kommen, diese per Callback (über synchronize)an das Hauptprogramm zurück meldet.

Das Hauptprogramm schreibt die Daten dann testweise per writeln() auf ein Konsolenfenster.

Das ganze funktioniert, zeigt aber einen merkwürdigen Effekt:

Die Konsole schreibt nur Daten, solange ich den Mauszeiger über das Hauptfenster bewege.

Was geht da schief? Habe ich was falsch gemacht?

Mavarik 5. Apr 2017 09:46

AW: Mutithreading: Konsolenausgabe hakt
 
Ohne code - versagt selbst meine Glaskugel momentan...

himitsu 5. Apr 2017 09:55

AW: Mutithreading: Konsolenausgabe hakt
 
MSDN-Library durchsuchenSetCursorPos in einem schnellen Timer.

Nun aber mal Ernst ... siehe Mavarik.

iphi 5. Apr 2017 10:01

AW: Mutithreading: Konsolenausgabe hakt
 
Mein Code ist momentan etwas länglich. Ich versuche den mal auf ein Minimum zu strippen.

Aber ungeachtet dessen:
Sind irgendwelche Probleme im Zusammenhang mit Multithreading und der Konsole bekannt?

Der schöne Günther 5. Apr 2017 10:01

AW: Mutithreading: Konsolenausgabe hakt
 
Mir fehlt auch die Vorstellung wie eine Konsolen-Anwendung etwas über
Delphi-Quellcode:
TThread.Synchronize(..)
in den Hauptthread schiebt. Gibt es für eine Delphi Konsolen-Anwendung da überhaupt einen Standardweg?

iphi 5. Apr 2017 10:12

AW: Mutithreading: Konsolenausgabe hakt
 
Es ist keine Konsolenanwendung, sondern eine ganz normale Fensteranwendung.
Ich habe dem Linker lediglich gesagt, er soll eine Konsole hinzufügen, zwecks Debugging per Writeln()-Kontrollausgaben.

Der Sammlerthread ruft per Synchronize einen TNotify-Event im Hauptthread auf, wenn Daten vorliegen. Wenn ich die Konsole entferne und statt dessen die Daten in eine Listbox schreibe, funktioniert komischerweise alles ganz normal. Gibts dafür irgendeine Erklärung?

Mavarik 5. Apr 2017 10:16

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1366483)
Mir fehlt auch die Vorstellung wie eine Konsolen-Anwendung etwas über
Delphi-Quellcode:
TThread.Synchronize(..)
in den Hauptthread schiebt. Gibt es für eine Delphi Konsolen-Anwendung da überhaupt einen Standardweg?

hmm...

Mein Consolenlogger macht es so:

Delphi-Quellcode:
      FOutputHandle := GetStdHandle( STD_OUTPUT_HANDLE );

Btw: Auch im Thread...

iphi 5. Apr 2017 11:06

AW: Mutithreading: Konsolenausgabe hakt
 
Ok, hier der Minimalcode, der das Problem zeigt:

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TPoll = class(TThread)
  private
    { Private declarations }
    POnData : TNotifyEvent;
  protected
    constructor Create(OnData: TNotifyevent);
    procedure Notify;
    procedure Execute; override;
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    i: integer;
    P: TPoll;
    procedure PData(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TPoll.Create(OnData: TNotifyevent);
begin
  inherited Create(true);
  Suspended:=false;
  FreeOnTerminate:=true;
  POnData:=OnData;
end;

procedure TPoll.Notify;
begin
if assigned(POnData) then POnData(nil);
end;

procedure TPoll.Execute;

begin
repeat
  sleep(500);
  Synchronize(Notify);
  until terminated;
end;

procedure TForm1.PData(Sender: TObject);
begin
inc(i);
writeln('data packet ',i);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i:=0;
P:=TPoll.Create(PData);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
P.Terminate;
end;

end.
Das ist eine ganz normale Delphi7-Fensteranwendung mit einem Fenster (Form1, leer), wobei bei den Linkeroptionen "Generate Console Application" angeklickt sein muss.
Nach meinem Verständniss müsste alle 0,5s eine Zeile auf die Konsole ausgegeben werden. Solange die Maus sich nicht bewegt, bleibt der Thread allerdings unerklärlicherweise stehen und es kommt nix.
Hoffentlich ist die Kristallkugel jetzt überflüssig...

haentschman 5. Apr 2017 11:28

AW: Mutithreading: Konsolenausgabe hakt
 
Moin...:P
Warum verpaßt du dem Thread nicht ein Event mit den "Arbeitsdaten". :gruebel:

...ungetestet:
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TWorkEvent = procedure(Sender: TObject; WorkStep: Integer);

  TPoll = class(TThread)
  private
    FStep: Integer;
    FOnWork: TWorkEvent;
    procedure SyncWork;
  protected
    constructor Create;
    property OnWork: TOnWorkEvent read FOnWork write FOnWork;
    procedure Execute; override;
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    FPoll: TPoll;
    procedure DoOnWork(Sender: TObject; WorkStep: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TPoll.Create;
begin
  inherited Create(True);
  Suspended := False;
  FreeOnTerminate := True;
  FStep := 0;
end;

procedure TPoll.Execute;
begin
  repeat
    sleep(500);
    Synchronize(SyncWork);
    // weitere Steps
  until terminated;
end;

procedure TPoll.SyncWork;
begin
  if Assigned(FOnWork) then
  begin
    FOnWork(Self, FStep);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FPoll := TPoll.Create;
  FPoll.OnWork := DoOnWork;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FPoll.Free;
end;

procedure TForm1.DoOnWork(Sender: TObject; WorkStep: Integer);
begin
  writeln('data packet ', WorkStep);
end;

end.

Mavarik 5. Apr 2017 11:29

AW: Mutithreading: Konsolenausgabe hakt
 
OK - Du gibst also nicht in ein Consolenfenster aus sondern es IST ein consolen Application?!?

Wofür dann das Form?

Hat ein Consolenprogramm überhaupt einen UI-Thread?

Uwe Raabe 5. Apr 2017 11:40

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von Mavarik (Beitrag 1366509)
Hat ein Consolenprogramm überhaupt einen UI-Thread?

In der Regel nicht. Dafür gibt es eine Abfrage in TApplication.CreateHandle auf IsConsole.

Wenn es lediglich um die Ausgabe geht, würde sich ein separates Form anbieten in dem die Ausgabe erfolgt. Das wäre dann wenigstens konsistent.

Solche Misch-Applikationen haben schon immer für Ärger gesorgt, da sie von Windows überhaupt nicht unterstützt werden (was natürlich manche Leute nicht davon abhält es trotzdem zu machen).

Mavarik 5. Apr 2017 11:51

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1366513)
(was natürlich manche Leute nicht davon abhält es trotzdem zu machen).

:thumb:

Blup 5. Apr 2017 11:56

AW: Mutithreading: Konsolenausgabe hakt
 
CheckSynchronize wird vom Applikationsobjekt einer VCL-Anwendung regelmäßig aufgerufen.
Dadurch werden Synchronize-Anforderungen von Threads verarbeitet.
In einer Konsolenanwendung muss man selbst für den regelmäßigen Aufruf dieser Methode sorgen.

Bei dieser Methode der Datenübergabe muss sowohl der Threaad als auch die Mainthread seine Arbeit unterbrechen.
Deshalb ist es besser asynchron mit Threads zu komunizieren, allerdings auch etwas aufwendiger.

Der schöne Günther 5. Apr 2017 11:57

AW: Mutithreading: Konsolenausgabe hakt
 
Was ist denn da jetzt der Unterschied in den Projektoptionen das zu setzen (habe ich noch nie gemacht)

und zum Test einfach mal mit
Delphi-Quellcode:
WinApi.Windows.AllocConsole()
ein Konsolenfenster aufzumachen in welches man dann mit
Delphi-Quellcode:
WriteLn(..)
einfach Dinge reinwirft?

Ich mache das gerne :oops:

iphi 5. Apr 2017 12:01

AW: Mutithreading: Konsolenausgabe hakt
 
@ haentschman:

Delphi-Quellcode:
 FPoll.OnWork := DoOnWork;
Mein D7-Compiler sagt da:
[Error] Unit1.pas(68): Incompatible types: 'regular procedure and method pointer'

@ Mavarik:

Zitat:

OK - Du gibst also nicht in ein Consolenfenster aus sondern es IST ein consolen Application?!?
Nein, ist sie nicht. Die Konsole habe ich nur zm Debuggen offen.

Zitat:

Wofür dann das Form?
Hab im Beispielprogramm alles bis auf die leere Form rausgeschmissen, da für die Erklärung des Problems unwesentlich.

@ Der schöne Günter:

Zitat:

und zum Test einfach mal mit WinApi.Windows.AllocConsole() ein Konsolenfenster aufzumachen
Hmmm, interessant. Wenn ich mit dieser Variante das Konsolenfenster aufmache, ist das Problem weg.

himitsu 5. Apr 2017 12:15

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1366513)
(was natürlich manche Leute nicht davon abhält es trotzdem zu machen).

Andersrum geht es problemlos.

Also VCL-Anwendung und da dann selber eine Console anzeigen (MSDN-Library durchsuchenAllocConsole)

haentschman 5. Apr 2017 12:19

AW: Mutithreading: Konsolenausgabe hakt
 
:P Soviel zum Testen...
Korrekt:
Delphi-Quellcode:
TWorkEvent = procedure(Sender: TObject; WorkStep: Integer) of object;

himitsu 5. Apr 2017 12:20

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von Mavarik (Beitrag 1366509)
Hat ein Consolenprogramm überhaupt einen UI-Thread?

Einen Mainthread hat jede Anwendung, aber in der Console gibt es die Message-Loop (Application.Run) natürlich nicht.

Zitat:

Zitat von iphi (Beitrag 1366520)
Nein, ist sie nicht. Die Konsole habe ich nur zm Debuggen offen.

Und wo kommt die her?
Das fehlt natürlich in deinem Beispielcode.

Mavarik 5. Apr 2017 12:36

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von himitsu (Beitrag 1366527)
Zitat:

Zitat von Mavarik (Beitrag 1366509)
Hat ein Consolenprogramm überhaupt einen UI-Thread?

Einen Mainthread hat jede Anwendung, aber in der Console gibt es die Message-Loop (Application.Run) natürlich nicht.

Das meinte ich - logischerweise - damit...

iphi 5. Apr 2017 12:38

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Und wo kommt die her?
Die klatscht der Linker dazu.

Sherlock 5. Apr 2017 12:42

AW: Mutithreading: Konsolenausgabe hakt
 
Damit Du das mit der Konsole entsorgen kannst: OutputDebugString verwenden.

Sherlock

himitsu 5. Apr 2017 15:24

AW: Mutithreading: Konsolenausgabe hakt
 
Zitat:

Zitat von iphi (Beitrag 1366529)
Die klatscht der Linker dazu.

Also im Delphi als Consolen-Anwendung erstellt und dann zusätzlich versucht die VCL zu verwenden? :stupid:

Wie bereits erwähnt, geht das nicht so einfach.
Andersrum, also VCL-Anwendung und da dann selber die Console anzeigen, das geht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz