简体   繁体   English

是否应该使用Thread.Sleep()检查进程是否仍在运行?

[英]Should I use Thread.Sleep() to check if a process is still running?

As title says, I'm currently making a WPF application and I need to detect if an application is running and do something when it's closed. 如标题所述,我目前正在制作WPF应用程序,我需要检测应用程序是否正在运行并在关闭时执行某些操作。 The way I'd thought of doing so is by running a separate Thread and checking every two seconds if the process is still running, something like this: 我想到的方法是运行一个单独的线程,每两秒钟检查一次进程是否仍在运行,如下所示:

while(Process.GetProcessesByName(processName).Length != 0) {
    Thread.Sleep(2000);
}

//Do something

Would this be a good solution, is there any other way of doing this? 这将是一个好的解决方案,还有其他方法吗?

Thanks 谢谢

Would this be a good solution? 这将是一个好的解决方案吗?

No, because it would waste an entire thread for nearly nothing. 不,因为这几乎浪费了整个线程。

Better use a timer, in a WPF application preferrably a DispatcherTimer: 最好在WPF应用程序中最好使用计时器,最好是DispatcherTimer:

var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };

timer.Tick += (s, e) =>
{
    if (Process.GetProcessesByName(processName).Length > 0)
    {
        // ...
    }
};

timer.Start();

If there would be a lengthy operation to be performed off the UI thread, you could use an async Tick event handler that awaits a Task (which would run on a thread pool thread in the background): 如果要在UI线程上执行冗长的操作,则可以使用等待Task的异步Tick事件处理程序(它将在后台在线程池线程上运行):

var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };

timer.Tick += async (s, e) =>
{
    if (Process.GetProcessesByName(processName).Length > 0)
    {
        await Task.Run(() =>
        {
            // lengthy operation here which runs on a thread pool thread
        });

        // udate UI here
    }
};

timer.Start();

Since you are already dealing with Processes, I would suggest just using it directly to determine if it has exited. 由于您已经在处理流程,因此建议您直接使用它来确定它是否已退出。 You can use the Exited event handler for your code. 您可以为代码使用Exited事件处理程序。 So, for instance: 因此,例如:

foreach (var process in Process.GetProcessesByName(processName))
{
  process.Exited += new EventHandler(DoSomething);
}

…

public void DoSomething(object sender, System.EventArgs e)
{
  // do something
}

This will call DoSomething when the process with that name ends. 当具有该名称的进程结束时,这将调用DoSomething

You could use a System.Timers.Timer that performs the check every x seconds: 您可以使用每隔x秒执行一次检查的System.Timers.Timer

public sealed partial class Window1 : Window, IDisposable
{
    private readonly System.Timers.Timer _timer = new System.Timers.Timer(TimeSpan.FromSeconds(2).TotalMilliseconds);

    public Window1()
    {
        InitializeComponent();
        _timer.Elapsed += _timer_Elapsed;
        _timer.Start();
    }

    private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (Process.GetProcessesByName("processName...").Length == 0)
        {
            _timer.Stop();
            _timer.Dispose();
            //do something...
        }
    }


    public void Dispose()
    {
        _timer.Dispose();
    }
}

Unlike the Tick event of a DispatcherTimer , the Elapsed event of a Timer is always queued for execution on a thread pool thread. DispatcherTimerTick事件不同, TimerElapsed事件始终在线程池线程中排队等待执行。

From the docs : 文档

If a System.Timers.Timer is used in a WPF application, it is worth noting that the System.Timers.Timer runs on a different thread than the user interface (UI) thread...Reasons for using a DispatcherTimer as opposed to a System.Timers.Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set on the DispatcherTimer . 如果在WPF应用程序中使用System.Timers.Timer ,则值得注意的是System.Timers.Timer在与用户界面(UI)线程不同的线程上运行...使用DispatcherTimer原因,而不是System.Timers.Timer是该DispatcherTimer运行同一个线程中的DispatcherDispatcherPriority可以在设置DispatcherTimer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM