C# 启动进程,然后引发事件以监视它们

C# 启动进程,然后引发事件以监视它们,c#,process,timer,C#,Process,Timer,我正在启动一个运行外部第三方软件包的流程。然后,我想启动一个计时器,每隔几秒钟触发一个事件,以监视这个过程的输出。以下是我用来启动流程的代码: Process process = new Process(); process.StartInfo.FileName = exe; process.StartInfo.Arguments = args; process.StartInfo.CreateNoWindow = true; process.StartInfo.WindowStyle = Pr

我正在启动一个运行外部第三方软件包的流程。然后,我想启动一个计时器,每隔几秒钟触发一个事件,以监视这个过程的输出。以下是我用来启动流程的代码:

Process process = new Process();
process.StartInfo.FileName = exe;
process.StartInfo.Arguments = args;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.BeginErrorReadLine();
RuntimeMonitor rtm = new RuntimeMonitor(OutputFile(), InputFile(), 5000);
process.WaitForExit();
rtm.Close();
运行时监视器的构造函数是:

public RuntimeMonitor(string _outfile,
                      string _title,
                      double intervalMs) // in milliseconds
{
    outFile = outfile;
    title = _title;
    timer = new System.Timers.Timer();
    timer.Interval = intervalMs;
    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_func);
    timer.AutoReset = true;
    timer.SynchronizingObject = null;
    timer.Start();
}
我得到的症状是直到进程结束(即在process.WaitForExit()完成之后)才调用timer_func。我认为计时器已过事件是异步触发的,但它似乎已被锁定

编辑:嗯,它变得很奇怪。我确实尝试将timer.SynchronizingObject设置为null,但没有效果。我还尝试使用System.Threading.Timer类,得到了相同的结果


还有一条信息。我确实发出了一个开始从进程收集数据的调用,但不确定这是否相关(即上面代码中的BeginErrorReadLine调用)

我不确定为什么计时器似乎没有启动。我把你的代码结构化了一点,试着测试一下。下面的代码工作得很好。也许你可以用它来让你的工作

void Main()
{
    Process process = new Process();
    process.StartInfo.FileName = "notepad.exe";
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;
    process.Start();
    RuntimeMonitor rtm = new RuntimeMonitor(5000);
    process.WaitForExit();
    rtm.Close();
}

public class RuntimeMonitor
{
    System.Timers.Timer timer;

    // Define other methods and classes here
    public RuntimeMonitor(double intervalMs) // in milliseconds
    {
        timer = new System.Timers.Timer();
        timer.Interval = intervalMs;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_func);
        timer.AutoReset = true;
        timer.Start();
    }

    void timer_func(object source, object e)
    {
        Console.WriteLine("Yes");
    }

    public void Close()
    {
        timer.Stop();
    }
}

我知道您的代码显示您在RuntimeMonitor构造函数中创建了计时器,但以防万一-检查计时器的属性并确保它为null。如果不是,那么这可能解释了你的情况。注意:在设计器中使用计时器也将设置属性-从MSDN:

如果在Windows窗体设计器的Visual Studio内部使用计时器,则SynchronizingObject将自动设置为包含计时器的控件。例如,如果将计时器放置在Form1(从Form继承)的设计器上,则计时器的SynchronizingObject属性将设置为Form1的实例


非常确定WaitForExit挂起了主线程,但是System.Timer只在主线程上运行。因此,您可以异步等待,也可以在新线程上运行计时器。也许不必使用WaitForExit,只需保持应用程序运行并检查进程即可。每次调用计时器时,HasExit bool都会退出。我认为在不同的线程上运行计时器是最好的选择。你能告诉我怎么做吗?你在代码片段中添加了一些零碎的东西,这表明我们不是在看真正的代码。不要这样做,发布你遇到问题的确切版本。我能想到的唯一一件事是rtm.Close()不做任何事情,因此使rtm对象接受垃圾收集。停止计时。不,这是确切的版本。我正在积极发展这一点,并张贴我所做/学到的。