Threads und die Console

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Displaced
Beiträge: 83
Registriert: So 12. Jul 2009, 10:08

Threads und die Console

Beitrag von Displaced »

Hi ho,

Ich hab da so ein kleines Problem.
Ich hab eine Konsolenanwendung die an sich meine richtige Anwendung per Thread startet.
Diese Anwendungen gibt nun ausgaben an die Konsole rüber..
Und ich habe gemerkt, dass wenn die Konsole gerade am schreiben ist, durch den Thread, und selbst was schreiben will, es zu einem Runerror(5) kommt.
Soweit ich das weiß, ist das ne Zugriffsverletzung. Logisch, mann kann schlecht gleichzeitig in den selben Buffer schreiben.
Gibts ne alternative um das zu handhaben, oder muss ich das ganze selbst steuern und ausgeben, mit ner Queue zum Beispiel?

Gruß
Displaced

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Threads und die Console

Beitrag von mschnell »

AFAIK: genau wie die LCL GUI-Objekte ist "write" zur Ausgabe an die Konsole nicht threadfest.

In einem Thread solltest Du die Konsole also nicht benutzen. Du müsstest die auszugebenden Daten an dem Mainthread übergeben (z.B. mit TThreadList) und den MainThread dann wecken. Das geht in einer GUI - Anwendung (z.B.) mit Application.QueueAsyncCall(). Leider gibt es keinen "Widget-Typ" der Event-Orientiertes Programmieren (also eine "Mainloop" im Mainhread) unterstützt, ohne dass eine GUI (wie GTK) verwendet wird. Bei no-GUI (Konsolen-) Anwendungen musst Du das Rad also leider jedes Mal selbst neu erfinden.

Empfehlung: lass es !

-Michael

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Threads und die Console

Beitrag von Socke »

Du solltest dir noch einmal das Design deiner Konsolenanwendung überdenken. Erstens: Warum muss der Nebenthread überhaupt etwas an den Benutzer ausgeben? Kann er als Ausgabekanal nicht einen anderen Weg wählen (Datei)?

Ansonsten bleibt wirklich nur noch eine Schleife im Haupt-Thread übrig. In dieser solltest du aber auf jeden Fall Events einsetzen, damit der Thread sich auch schlafen legen kann. Dabei gibt es nur das Problem, dass dein Programm dann nicht mehr auf Benutzereingaben reagieren kann, während es auf die Nachricht eines anderen Threads wartet.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Displaced
Beiträge: 83
Registriert: So 12. Jul 2009, 10:08

Re: Threads und die Console

Beitrag von Displaced »

Ich hab das Problem, dass es nicht anders geht.
Es geht um eine Serversoftware die Ausgaben produziert, das ist ein "muss" für mich.
Das ganze jetzt selbst in die Hand zu nehmen und zu steuern wäre nicht soooo das Problem.
Mein Problem ist, dass die Konsole auch eingaben entgegen nehmen soll.
Und ReadLn blockiert ja soweit ich das weiß. Wie also produzier ich eine Schleife, die die Queue abfertigt und gleichzeitig auf eine Eingabe wartet?

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Threads und die Console

Beitrag von mschnell »

Das ist das "alte" Problem, dass es in Lazarus eben keine no-GUI Application (und damit den entsprechenden "Widget-Type" (Project Options ->Build Mode - LCLWidgetType ) gibt, die ohne GUI-Bindung Events verarbeiten kann.

Falls Du das nicht selber basteln willst. Habe ich 'mal angefangen, ist aber sehr komplex, wenn man es so machen will, dass es vernünftig in das Lazarus - Widget Type (aka GUI Interface) System einbauen will.

MSE-IDE dagegen hat eine funktionsfähige NoGUIApplication. Vielleicht bedienst Du Dich besser da (hier gibt es ein SubForum für MSE).

-Michael
Zuletzt geändert von mschnell am Mo 26. Sep 2011, 12:30, insgesamt 1-mal geändert.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Threads und die Console

Beitrag von mschnell »

Displaced hat geschrieben: Wie also produzier ich eine Schleife, die die Queue abfertigt und gleichzeitig auf eine Eingabe wartet?
In C geht das mit (old style) "select()" oder (moderner) "epoll()". In Lazarus ist das nicht vorgesehen. (keine Ahnung ob/wie MSE das anbietet). Natürlich kannst Du irgendwie die C - Library für select() oder epoll() aufrufen oder eine C- oder ASM- Funktion dafür schreiben und einbinden.

Wenn Du select() oder epoll() verwendest muss die Event-Quelle eine Datei sein (z.B. einen Pipe).

Eine noch "kreativere" (und m.E. sehr low level und old style) Variante wären "signals".

-Michael

Displaced
Beiträge: 83
Registriert: So 12. Jul 2009, 10:08

Re: Threads und die Console

Beitrag von Displaced »

Also der Thread der Benutzerausgaben produziert ist einfach nur das Programm selbst, welches Ausgelagert wurde.

Was haltet ihr davon, wenn ich einen ExtraThread produziere, der nur die Ausgaben handhabt. Sprich alles was an ausgaben zu tätigen ist, macht ein seperater Thread, damit der Main Thread auf Eingaben warten kann und das ProgrammThread, ungestört seine Arbeit tätigen kann.
Was mich jetzt interessieren würde ist:
Wenn ich einen Thread in "Suspend" mode schicke, bleibt der dann einfach da wo der grad ist stehen, oder beendet er die Execute schleife und wird beim "Resume" die Execute schleife wieder ausführen?

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Threads und die Console

Beitrag von Socke »

Displaced hat geschrieben:Wenn ich einen Thread in "Suspend" mode schicke, bleibt der dann einfach da wo der grad ist stehen, oder beendet er die Execute schleife und wird beim "Resume" die Execute schleife wieder ausführen?
Verwende Events um den Thread schlafen zu legen; die sind sicherer zu handhaben und funktionieren auf allen Betriebssystemen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Displaced
Beiträge: 83
Registriert: So 12. Jul 2009, 10:08

Re: Threads und die Console

Beitrag von Displaced »

Okay. Gibt 's dafür irgendwo ein Beispiel was ich mir angucken kann?

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Threads und die Console

Beitrag von mschnell »

Socke hat geschrieben:Verwende Events um den Thread schlafen zu legen; die sind sicherer zu handhaben und funktionieren auf allen Betriebssystemen.
Wie gesagt: Lazarus erlaubt nur ein Event-gesteuertes Programmieren, wenn eine GUI (Windows, GTK, QU, ...) angebunden ist, ansonsten (und das ist hier wohl gewünscht) gibt es keine Event-Queue.

Oder Meinst Du TEvent, was eine Semaphore ist und kein Event wie in "eventorientierte Programmierung" ?

-Michael
Zuletzt geändert von mschnell am Mo 26. Sep 2011, 14:10, insgesamt 1-mal geändert.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Threads und die Console

Beitrag von mschnell »

Displaced hat geschrieben:Was haltet ihr davon, wenn ich einen ExtraThread produziere, der nur die Ausgaben handhabt. Sprich alles was an ausgaben zu tätigen ist, macht ein seperater Thread, damit der Main Thread auf Eingaben warten kann und das ProgrammThread, ungestört seine Arbeit tätigen kann.
Das könnte gehen. (Ohne GUI ist die Unterscheidung zwischen dem "MainThread" und andren Threads nicht wirklich nötig.)

Damit aber eine Art Bedienoberfläche zu gestalten, könnte aber etwas schwierig werden.
Displaced hat geschrieben:Wenn ich einen Thread in "Suspend" mode schicke, bleibt der dann einfach da wo der grad ist stehen, oder beendet er die Execute schleife und wird beim "Resume" die Execute schleife wieder ausführen?
Er bleibt einfach stehen. "Suspend" ist aber keine wirklich saubere Methode zur Synchronisation von Threads. "TThread.Synchronize" verwendet (wie Application.QueuAsyncCall) Events und funktioniert deshalb bei Lazarus nicht ohne GUI). Es bleiben also für die Synchronisation Blocking reads (Z.B. auf Pipes) oder Semaphoren (TCriticalSection, u.U. TEvent).

-Mchael

Antworten