Должен ли я использовать Thread.Sleep (), чтобы проверить, запущен ли еще процесс? - PullRequest
0 голосов
/ 23 мая 2019

Как видно из заголовка, я в настоящее время создаю приложение WPF, и мне нужно определить, запущено ли приложение, и что-то делать, когда оно закрыто. Я подумал об этом, запустив отдельный поток и проверяя каждые две секунды, работает ли процесс, что-то вроде этого:

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

//Do something

Это было бы хорошим решением, есть ли другой способ сделать это?

Спасибо

Ответы [ 3 ]

3 голосов
/ 23 мая 2019

Это было бы хорошим решением?

Нет, потому что это потратило бы впустую весь поток почти ничего.

Лучше использовать таймер в приложении WPFпредпочтительно DispatcherTimer:

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

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

timer.Start();

Если бы выполнялась длительная операция из потока пользовательского интерфейса, вы могли бы использовать обработчик событий async Tick, ожидающий Task (которыйзапустить в фоновом потоке потоков):

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();
1 голос
/ 24 мая 2019

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

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

…

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

Это вызовет DoSomething, когда процесс с таким именем завершится.

0 голосов
/ 23 мая 2019

Вы можете использовать System.Timers.Timer, который выполняет проверку каждые x секунд:

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

В отличие от Tick события DispatcherTimer, Elapsed событие Timer являетсявсегда в очереди на выполнение в потоке пула потоков.

Из документов :

Если System.Timers.Timer используется в приложении WPF, то стоитотмечая, что System.Timers.Timer работает в потоке, отличном от потока пользовательского интерфейса (UI) ... Причины использования DispatcherTimer в отличие от System.Timers.Timer состоят в том, что DispatcherTimer работает в том же потоке, что и Dispatcher и DispatcherPriority могут быть установлены на DispatcherTimer.

...