Запуск процессов, затем инициирование событий для их мониторинга. - PullRequest
3 голосов
/ 27 января 2012

Я запускаю процесс, который запускает внешний сторонний пакет. Затем я хотел бы запустить таймер, который запускает событие каждые несколько секунд, чтобы отслеживать результаты этого процесса. Вот код, который я использую для запуска процесса:

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

Симптом, который я получаю, заключается в том, что timer_func не вызывается до тех пор, пока процесс не завершится (т.е. после process.WaitForExit (); завершается). Я думал, что событие прошедшего таймера сработало асинхронно, но, похоже, оно заблокировано

РЕДАКТИРОВАТЬ: ну, это становится незнакомым. Я попытался установить timer.SynchronizingObject в null, но безрезультатно. Я также попытался использовать класс System.Threading.Timer и получил тот же результат.

Еще одна информация. Я делаю вызов, чтобы начать сбор данных из процесса, но не уверен, что это актуально (то есть вызов BeginErrorReadLine в приведенном выше коде)

Ответы [ 2 ]

2 голосов
/ 27 января 2012

Я не уверен, почему ваш таймер не срабатывает.Я взял ваш код и немного структурировал его, чтобы попробовать и проверить это.Следующий код работает просто отлично.Возможно, вы можете использовать его, чтобы заставить работать.

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();
    }
}
0 голосов
/ 27 января 2012

Я знаю, что ваш код показывает, что вы создаете таймер внутри конструктора RuntimeMonitor, но на всякий случай - проверьте свойство Timer.SynchronizingObject вашего Timer и убедитесь, что он равен нулю.Если это не так, то это может объяснить вашу ситуацию.Обратите внимание, что использование таймера в конструкторе также приведет к установке этого свойства - из MSDN:

Если в Visual Studio в конструкторе Windows Forms используется таймер, для SynchronizingObject автоматически устанавливается элемент управления, содержащийТаймер.Например, если вы поместите Timer в конструктор для Form1 (который наследуется от Form), для свойства SynchronizingObject объекта Timer будет установлен экземпляр Form1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...