背景

我正在为node.js应用程序编写C#包装器。在这个包装器中,我通过Process.RedirectStandardOutput连续读取标准输出。该事件在onOutputDataReceived类的实例中绑定(bind)到函数ProcessManager。在同一实例中,还存在一个定制事件系统的实例。

[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;
    });

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



,据我了解,我的问题是:
onOutputDataReceived在其自己的线程中异步执行。由于该线程仅用于处理输出,因此继续调用事件,因此我无意间对包装器进行了多线程处理,这给实现它的任何人都变得更加艰辛。

基本上

一旦接收到新的输出数据,我就需要在维护其余eventSystem.call()实例的同一线程中运行ProcessManager行。关于如何实现最佳效果的任何想法?

我想到的解决方案是这样的

[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的使用方式不同步...这是一个不相关的错误。

10-06 03:31