重新同步Process.RedirectStandardOutput

本文关键字:Process RedirectStandardOutput 同步 新同步 | 更新日期: 2024-09-24 10:29:58

背景

我正在为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;
    });

运行时,应用程序崩溃,并显示消息

跨线程操作无效:控件"button1"从线程访问,而不是在上创建的线程

据我所知,我的问题是:

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毫秒进行一次轮询,这感觉不是一个干净的解决方案。此外,在我看来,这样的解决方案在没有收到消息的情况下成本太高,而在收到消息的时候速度太慢。

重新同步Process.RedirectStandardOutput

执行nodejs进程并读取其输出的代码不需要了解事件订阅者的线程需求。使用户满足自己的要求:

(a) =>
{
    Invoke(new Action(() => button1.Text = someValue)); //marshal to UI thread
}

您的临时解决方案将不起作用,因为它会阻塞UI线程。

此外,waiting正在以不同步的方式使用。。。这是一个无关的错误。