背景再同期Process.RedirectStandardOutput
私はNode.jsのアプリケーションのためのC#ラッパーを書いています。このラッパーでは、私はProcess.RedirectStandardOutput
経由で標準出力を継続的に読んでいました。このイベントは、クラスProcessManager
のインスタンスの関数onOutputDataReceived
にバインドされています。この同じ例では、カスタムイベントシステムのインスタンスもあります。
[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);
}
[...]
}
問題イベントが呼び出されている場合に発生します。次に、ラッパーを使用したwinformsアプリケーションの例を示します。
Wrapper.ProcessManager procMan;
procMan.eventSystem.on(eventName, (a) =>
{
button1.Text = someValue;
});
実行すると、メッセージ
上に作成されたスレッド以外のスレッドからアクセスコントロール「ボタン1」クロススレッド操作でアプリケーションがクラッシュしていない有効な:それは
問題がわかりましたが、これは次のとおりです。
onOutputDataReceived
は、それ自身のスレッドで非同期に実行されています。この同じスレッドは、出力を処理することを意図したものであり、イベントを呼び出すために実行されます。私は意図せずに自分のラッパーをマルチスレッドしています。
基本的に、
私はすぐに新しい出力データを可能として受信されているように、ProcessManager
インスタンスの残りの部分を維持して同じスレッドでラインeventSystem.call()
を実行する必要があります。この最高の成果を達成するためのアイデアはありますか?私が考えてきた
ソリューション私の知る限り見ることができるように、これはポーリングのいくつかの種類ごとのxを伴うだろうこの
[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());
}
のようなものですミリ秒で、クリーンなソリューションのようには感じられません。また、メッセージが受信されていない場合や一部のメッセージが遅すぎる場合には、そのようなソリューションが高価すぎるように見えます。
私はそのように以前は考えていませんでした(まだマルチスレッドには慣れていませんが)、それは理にかなっています。 –