重新同步 Process.RedirectStandardOutput
Re-synchronize Process.RedirectStandardOutput
背景
我正在为 node.js 应用程序编写一个 c# 包装器。在这个包装器中,我通过 Process.RedirectStandardOutput
连续读取标准输出。在 class 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;
});
当 运行 时,应用程序崩溃并显示消息
Cross-thread operation not valid: Control 'button1' accessed from a thread other than the thread it was created on
我的问题,据我了解,是这样的:
onOutputDataReceived
正在其自己的线程中异步执行。由于同一个线程,仅用于处理输出,继续调用事件,我无意中对我的包装器进行了多线程处理,使实施它的任何人的生活都变得更加困难。
基本上,
我需要在维护 ProcessManager
实例的其余部分的同一线程中 运行 行 eventSystem.call()
,尽快收到新的输出数据。关于如何做到最好有什么想法吗?
一个解决方案我想到的是这样的
[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());
}
据我所知,这将涉及每 x 毫秒进行某种轮询,这感觉不像是一个干净的解决方案。另外,在我看来,这样的解决方案对于没有收到消息的情况来说太昂贵了,而对于收到消息的情况来说太慢了。
执行 nodejs 进程并读取其输出的代码不需要了解事件订阅者的线程要求。让订阅者满足自己的要求:
(a) =>
{
Invoke(new Action(() => button1.Text = someValue)); //marshal to UI thread
}
您的暂定解决方案无效,因为它会阻塞 UI 线程。
此外,waiting
正在以不同步的方式使用...这是一个不相关的错误。
背景
我正在为 node.js 应用程序编写一个 c# 包装器。在这个包装器中,我通过 Process.RedirectStandardOutput
连续读取标准输出。在 class 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;
});
当 运行 时,应用程序崩溃并显示消息
Cross-thread operation not valid: Control 'button1' accessed from a thread other than the thread it was created on
我的问题,据我了解,是这样的:
onOutputDataReceived
正在其自己的线程中异步执行。由于同一个线程,仅用于处理输出,继续调用事件,我无意中对我的包装器进行了多线程处理,使实施它的任何人的生活都变得更加困难。
基本上,
我需要在维护 ProcessManager
实例的其余部分的同一线程中 运行 行 eventSystem.call()
,尽快收到新的输出数据。关于如何做到最好有什么想法吗?
一个解决方案我想到的是这样的
[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());
}
据我所知,这将涉及每 x 毫秒进行某种轮询,这感觉不像是一个干净的解决方案。另外,在我看来,这样的解决方案对于没有收到消息的情况来说太昂贵了,而对于收到消息的情况来说太慢了。
执行 nodejs 进程并读取其输出的代码不需要了解事件订阅者的线程要求。让订阅者满足自己的要求:
(a) =>
{
Invoke(new Action(() => button1.Text = someValue)); //marshal to UI thread
}
您的暂定解决方案无效,因为它会阻塞 UI 线程。
此外,waiting
正在以不同步的方式使用...这是一个不相关的错误。