![]() |
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? |
AW: Mutithreading: Konsolenausgabe hakt
Ohne code - versagt selbst meine Glaskugel momentan...
|
AW: Mutithreading: Konsolenausgabe hakt
|
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? |
AW: Mutithreading: Konsolenausgabe hakt
Mir fehlt auch die Vorstellung wie eine Konsolen-Anwendung etwas über
Delphi-Quellcode:
in den Hauptthread schiebt. Gibt es für eine Delphi Konsolen-Anwendung da überhaupt einen Standardweg?
TThread.Synchronize(..)
|
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? |
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
Mein Consolenlogger macht es so:
Delphi-Quellcode:
FOutputHandle := GetStdHandle( STD_OUTPUT_HANDLE );
Btw: Auch im Thread... |
AW: Mutithreading: Konsolenausgabe hakt
Ok, hier der Minimalcode, der das Problem zeigt:
Delphi-Quellcode:
Das ist eine ganz normale Delphi7-Fensteranwendung mit einem Fenster (Form1, leer), wobei bei den Linkeroptionen "Generate Console Application" angeklickt sein muss.
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. 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... |
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. |
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? |
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
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). |
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
|
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. |
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:
ein Konsolenfenster aufzumachen in welches man dann mit
WinApi.Windows.AllocConsole()
Delphi-Quellcode:
einfach Dinge reinwirft?
WriteLn(..)
Ich mache das gerne :oops: |
AW: Mutithreading: Konsolenausgabe hakt
@ haentschman:
Delphi-Quellcode:
Mein D7-Compiler sagt da:
FPoll.OnWork := DoOnWork;
[Error] Unit1.pas(68): Incompatible types: 'regular procedure and method pointer' @ Mavarik: Zitat:
Zitat:
@ Der schöne Günter: Zitat:
|
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
Also VCL-Anwendung und da dann selber eine Console anzeigen ( ![]() |
AW: Mutithreading: Konsolenausgabe hakt
:P Soviel zum Testen...
Korrekt:
Delphi-Quellcode:
TWorkEvent = procedure(Sender: TObject; WorkStep: Integer) of object;
|
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
Zitat:
Das fehlt natürlich in deinem Beispielcode. |
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
|
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
|
AW: Mutithreading: Konsolenausgabe hakt
|
AW: Mutithreading: Konsolenausgabe hakt
Zitat:
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 17:54 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz