如何在process.waitforexit()中运行计时器?

时间:2014-07-17 03:03:09

标签: c# .net multithreading process timer

我的表单包含两个控件:button1和timer1

timer1.Interval=1000; timer1.Enable=true;    

单击button1时,将启动Windows上的应用程序。例如:记事本会显示。
但是当记事本显示时,timer1没有运行 如何使timer1这样运行?

我的代码:

private void button1_Click(object sender, EventArgs e)
{
    Process pro = new Process();
    pro.StartInfo.FileName = "notepad";
    pro.StartInfo.Arguments = "";
    pro.Start();
    pro.WaitForExit();
}
private void timer1_Tick(object sender, EventArgs e)
{
    DateTime dtime = DateTime.Now;
    string date_time = dtime.ToString("dd/MM/yyyy HH:mm:ss");
    textBox2.Text = date_time;
}

3 个答案:

答案 0 :(得分:4)

来自Process.WaitForExit

  

指示Process组件无限期等待以使相关进程退出。

您的计时器正在尝试调用timer1_Tick,但您的UI线程目前仍在等待进程退出,但它不会。

您有两种选择来解决这个问题:

  1. 如果您真的不需要等待,只需删除对WaitForExit的调用
  2. 如果您确实需要在流程退出时收到通知,请将Process.EnableRaisingEvents设置为true并注册Process.Exited活动

答案 1 :(得分:1)

pro.WaitForExit();使UI线程冻结,因此无法更新。

要阻止用户执行操作,您可以在进程运行时禁用某些控件。当用户关闭流程时,您可以订阅process.Exited事件并启用控件。

private void button1_Click(object sender, EventArgs e)
{
    Process pro = new Process();
    pro.StartInfo.FileName = "notepad";
    pro.StartInfo.Arguments = "";
    pro.Start();
    button1.Enabled = false;
    pro.EnableRaisingEvents = true;
    pro.Exited += pro_Exited;
}

void pro_Exited(object sender, EventArgs e)
{
     button1.Invoke((MethodInvoker) delegate { button1.Enabled = true; });
}

<强>更新

如另一个答案所示,您应将EnableRaisingEvents属性设置为true。 另外pro_Exited方法将在不同的线程中运行,因此您需要使用Control.Invoke方法来更改UI。

更新2 如果无法删除pro.WaitForExit();,则可以使用其他计时器,因为System.Windows.Forms.Timer正在UI线程中运行并被其阻止。

private System.Threading.Timer timer = new System.Threading.Timer(Callback);

public Form()
{
    InitializeComponent();
    timer.Change(0, 1000);
}

private void Callback(object state)
{
    DateTime dtime = DateTime.Now;
    string date_time = dtime.ToString("dd/MM/yyyy HH:mm:ss");
    button1.Invoke((MethodInvoker)delegate { textBox1.Text = date_time; });
}

textBox打开时,它不会更新process,但计时器将会运行并且可以完成一些工作。

更新3 如果是多个流程,您可以对它们进行计数,并在pro_Exited方法中检查活动流程的数量。

private volatile int activeProcessCount = 0;
private void pro_Exited(object sender, EventArgs e)
{
    activeProcessCount--;
    if (activeProcessCount == 0)
    {
        button1.Invoke((MethodInvoker) delegate { button1.Enabled = true; });
    }
}
private void button1_Click(object sender, EventArgs e)
{
    //code
    activeProcessCount = 2;
    pro1.Start();
    pro2.Start();
}

答案 2 :(得分:1)

WaitForExit()是&#34;阻止&#34;你的界面从刷新,调用只是等待进程退出。作为替代方案,如果您需要在退出流程时执行此操作:

        private void button1_Click(object sender, EventArgs e)
        {
            Process pro = new Process();
            pro.StartInfo.FileName = "notepad";
            pro.StartInfo.Arguments = "";

            //if you need to do something when the process  exits do this:
            pro.EnableRaisingEvents = true;
            pro.Exited += new EventHandler(pro_Exited);
            pro.Start();
            //pro.WaitForExit();
        }

        void pro_Exited(object sender, EventArgs e)
        {
            //do what you need here...
        }

相反,您可以使用BackGroundWorker启动该过程。