HintergrundRe-Synchronisierung Process.RedirectStandardOutput
Ich bin ein C# Wrapper für eine node.js Anwendung zu schreiben. In diesem Wrapper lese ich kontinuierlich die Standardausgabe über Process.RedirectStandardOutput
. Das Ereignis ist an die Funktion onOutputDataReceived
in einer Instanz der Klasse ProcessManager
gebunden. In derselben Instanz gibt es auch eine Instanz eines benutzerdefinierten Ereignissystems.
[ProcessManager
]
EventSystem eventSystem;
private void Start()
{
[...]
process.OutputDataReceived += onOutputDataReceived;
[...]
}
private void onOutputDataReceived(object sender, DataReceivedEventArgs e)
{
[...]
eventSystem.call(eventName, args);
}
[EventSystem
]
List<EventHandler> eventList;
public Boolean call(String eventName, dynamic args)
{
[...]
foreach (EventHandler handler in eventList)
{
handler(args);
}
[...]
}
Das Problem tritt auf, wenn das Ereignis aufgerufen wird. Hier ist ein Beispiel aus einer winforms-Anwendung, die meinen Wrapper verwendet.
Wrapper.ProcessManager procMan;
procMan.eventSystem.on(eventName, (a) =>
{
button1.Text = someValue;
});
Sobald er ausgeführt wird, stürzt die Anwendung mit der Meldung
Cross-Thread-Betrieb nicht gültig: Control 'button1' von einem Thread zugegriffen andere als das Gewinde auf erstellt wurde
Meine Frage, wie ich es verstehe, ist dies:
onOutputDataReceived
wird asynchron in einem eigenen Thread ausgeführt. Da derselbe Thread, der nur die Ausgabe verarbeiten soll, die Ereignisse fortsetzt, bin ich unbeabsichtigt Multithreading in meinem Wrapper, was das Leben für jeden, der ihn implementiert, erschwert.
Grundsätzlich,
ich brauche die Leitung eventSystem.call()
in demselben Thread auszuführen, die den Rest der ProcessManager
Instanz halten, sobald neue Ausgangsdaten wie möglich empfangen wurden. Irgendwelche Ideen, wie dies am besten erreicht werden kann?
Eine Lösung dachte ich habe von so etwas wie dieses
[ProcessManager
]
Queue<string> waiting = new Queue<string();
EventSystem eventSystem;
private void onOutputDataReceived(object sender, DataReceivedEventArgs e)
{
[...]
waiting.Enqueue(eventName);
}
private void WhenReady()
{
while(waiting.Count > 0)
eventSystem.call(waiting.Dequeue());
}
Soweit ich sehen kann, dies würde bedeuten, eine Art Polling jedes x Millisekunden, die sich nicht wie eine saubere Lösung anfühlt. Es scheint mir auch so, als wäre eine solche Lösung viel zu teuer für den Fall, dass keine Nachrichten empfangen werden und zu langsam für einige.
Ich habe noch nicht so darüber nachgedacht (noch nicht an Multithreading gewöhnt), aber es macht Sinn. –