Forum: PC-Programmierung C# Prozess kein unabhängiger Thread?


von Dirac I. (dirac-impuls)


Lesenswert?

Hallo,

ich habe eine Klasse, in der ein Prozess aufgerufen wird, mit dem über 
Stdin und Stdout gequatscht wird.

Wenn ich nun eine Nachricht schicke, etwa
1
process.StandardInput.WriteLine("ping");
 dann kommt per event nach sehr kurzer Zeit eine Antwort
1
private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
2
{
3
  Console.WriteLine("Ping erfolgreich");
4
}

Nun möchte ich aber nach dem abschicken in einer while Schleife auf die 
Antwort warten.
1
volatile bool pingReceived;
2
WaitForPing()
3
{
4
  pingReceived = false;
5
  process.StandardInput.WriteLine("ping");
6
  while(!pingReceived) ;
7
}
8
9
process_OutputDataReceived(object sender, DataReceivedEventArgs e)
10
{
11
  pingReceived = true;
12
}

Allerdings warte ich bis heute auf die Pingantwort. Sehe ich es somit 
richtig, dass ein Process immer ein untergeordneter Thread ist, der nur 
arbeiten darf, wenn der übergeordnete Thread ihn lässt? Da der 
Hauptthread nichts anderes macht, als eine boolsche Variable abzufragen 
find ich es schon ein bisschen schwach, dass mein Prozess keinen 
einzigen Taktzyklus abbekommmt. Habe ich etwas übersehen, kann man da 
noch irgendwo was einstellen?

von Dirac I. (dirac-impuls)


Lesenswert?

Ich hätte vielleicht noch dazu schreiben sollen, dass der Debugger 
tatsächlich in der while Schleife stehen bleibt und diese nie verlassen 
wird. Da die Kommunikation zum Process in dem Unterprogramm 
protokolliert wird erkenne ich, dass mit der while Schleife auch 
tatsächlich keine Antwort zurückgeschickt wird während jedoch der "ping" 
Befehl noch erhalten wird. Entferne ich die while Schleife so kommt 
sofort eine Antwort.

Hier nochmal die aktuelle while Schleife:
1
WaitForPing()
2
{
3
  pingReceived = false;
4
  process.StandardInput.WriteLine("ping");
5
  while(!pingReceived) ;
6
  Console.WriteLine("Warum werde ich nie aufgerufen?");
7
}

von Kaj (Gast)


Lesenswert?

Zeig doch einfach den ganzen Code, dann müssen wir nicht erst unsere 
Kristallkugeln rausholen...
Ist pingReceived threadsafe?

Dirac I. schrieb:
> Sehe ich es somit
> richtig, dass ein Process immer ein untergeordneter Thread ist,
Nein. Prozess > Thread
Prozess != Thread
Ein Thread ist ein leichtgewichtiger Unterprozess von einem Prozess. Ein 
Prozess ist aber mit Sicherheit nicht dem Thread untergeordnet.
https://de.wikipedia.org/wiki/Thread_%28Informatik%29#Bedeutungsunterschied_.28Kernel-.29_Thread_gegen.C3.BCber_Prozess.2C_Task_und_User_Thread
https://de.wikipedia.org/wiki/Thread_%28Informatik%29#.NET

Dirac I. schrieb:
> der nur
> arbeiten darf, wenn der übergeordnete Thread ihn lässt?
Wer wann wo wieviel CPU-Zeit bekommt, verwaltet das OS (der Scheduler). 
Deswegen startest du ja einen neuen Prozess/Thread, damit eine aufgabe 
unabhängig vom Rest erledigt werden kann.

Dirac I. schrieb:
> Habe ich etwas übersehen
Mit Sicherheit

Dirac I. schrieb:
> kann man da
> noch irgendwo was einstellen?
Ja, könnte man (Stichwort: Prioritäten), aber das ist nicht das 
Problem, das du hast. Außerdem pfuscht du damit dem Scheduler in die 
Arbeit, und der weiß deutlich besser was er da macht, als du. Wie bei 
Compilern auch.

Ob da wirklich ein neuer Prozess/Thread gestartet wird, kannst du im 
Task-Manager sehen.

von Dirac I. (dirac-impuls)


Lesenswert?

Hallo Kaj,

vielen Dank für deine Antwort. Die Threadsicherheit kanns denke ich 
nicht sein, weil der Debugger mir Bescheid geben würde. Alle anderen 
Daten werden immer erfolgreich aus und in den Process hin und her 
geschoben. Auch das Schlüsselwort "volatile" ist hier nicht notwendig.

Das Programm ist einfach zu groß, als dass ich es hier posten könnte 
oder sollte. Es handel sich hierbei um ein kleines Teilproblem eines 
großes Programms. Du hast aber recht, dass ich vergessen habe zu 
erwähnen, dass es sich um eine Windows Forms Awendung handelt.

Ich bin dem Problem jedoch näher gekommen. Der aufgerufene Prozess kann 
beschäftigt oder unbeschäftigt sein, was per Befehl im Stdin/Stdout vom 
oberen C#Programm kommt. In beiden Fällen soll und gibt er eine Antwort 
auf die Pingabfrage.

Prozess unbeschäftigt -> WaitForPing funktioniert immer.
Prozess beschäftigt -> Mit der while Schleife bleibt das Programm 
hängen, ohne while Schleife kommt eine Pingantwort per Event.

Nur wenn die while Schleife vorhanden ist und der Prozess beschäftigt 
ist, bleibt das Programm hängen.


Interessanterweise reicht es nicht aus per Button dem Prozess den Befehl 
zu schicken unbeschäftigt zu sein und direkt dahinter zu pingen. Erst 
wenn ich per ButtonA ihn unbeschäftigt mache und ihn danach per ButtonB 
pinge, kommt er auch mit der while Schleife klar.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Dirac I. schrieb:
> Nun möchte ich aber nach dem abschicken in einer while Schleife auf die
> Antwort warten.

WIeso? Wenn es schon eventbasiert geht kann man das doch nutzen? 
Ansosnten ist beim Busy-Loop immer wenigstens eine kleine Wartezeit 
empfehlenswert um die CPU Last nicht unnötig hoch zu halten.

von Rolf M. (rmagnus)


Lesenswert?

Dirac I. schrieb:
> Nun möchte ich aber nach dem abschicken in einer while Schleife auf die
> Antwort warten.

Du willst also die CPU-Last auf 100% treiben, um ein Flag abzufragen? 
Schlechte Idee.

> Habe ich etwas übersehen, kann man da noch irgendwo was einstellen?

Wird die Event-Loop denn überhaupt noch abgearbeitet, wenn dein Programm 
in einer while-Schleife festhängt?

von Dirac I. (dirac-impuls)


Lesenswert?

Hallo Läubi,

vielen Dank für deinen Hinweis, es war der richtige.

Läubi .. schrieb:
> WIeso? Wenn es schon eventbasiert geht kann man das doch nutzen?

Weil es nur sehr, sehr selten aufgerufen wird, nur sehr wenig Zeit in 
Anspruch nimmt aber mehrmals im Quellcode benötigt wird.

Ich habe hier übrigens ein sehr interessantes Verhalten festgestellt:

Vorausgesetzt der Prozess arbeitet und es gibt die while Schleife:

Kein Sleep Befehl -> Funktioniert nie
Zu kleiner Sleep Befehl (in meinem Fall bis ca. 50 ms) -> Funktioniert 
nur, wenn Flag-Variable voatile ist
Ausreichend großer Sleep Befehl (in meinem Fall ab ca. 100 ms) -> 
Funktioniert immer, auch wenn die Flag-Variable nicht volatile ist.

von Dirac I. (dirac-impuls)


Lesenswert?

> Wird die Event-Loop denn überhaupt noch abgearbeitet, wenn dein Programm
> in einer while-Schleife festhängt?

Nein. Aber jetzt geht es. Vielen Dank auch an dich!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.