如何在不停止 WPF 中的计时器的情况下使用线程使用进程?

How to use process using Threads without stoping a timer in WPF?

这是一个小指南,可帮助解决计时器在使用默认应用程序打开文件时停止的问题。

如果您在 C# WPF 中使用计时器,您会注意到计时器将停止工作,直到文件关闭,这可能不是您想要的行为。

例如,假设您希望在要向用户显示的文件打开时立即启动计时器。当用户看到或阅读您希望计时器继续的文件时。如果不使用线程,计时器将不会继续工作,直到文件关闭。

遇到的问题是这样的: 我有一个计时器,它通过按下按钮 (btnTache1) 启动,但是当我使用 System.Diagnostics.Process 使用另一个按钮 (btnVideo1) 使用默认应用程序打开文件时它会停止。它只会在文件关闭后恢复。

这是程序组件的简要说明: 有一个按钮可以显示名为 btnVideo1 的媒体 按钮的 onclick 事件定义了计时器 _timer1 和要向用户显示的文件 _media1 以及计时器使用的倒计时 _startingTimer1 设置为 30 秒。

代码如下:

private int _startingTimer1;
private string _media1;
DispatcherTimer _timer1 = new DispatcherTimer();

private void btnVideo1_Click(object sender, RoutedEventArgs e)
{
    _startingTimer1 = 30; // 30 seconds
    // stop timer if already started
    if (_timer1.IsEnabled == true)
    {
        _timer1.Stop();                
    }

    // configure timer 
    _timer1 = new DispatcherTimer();
    _timer1.Interval = TimeSpan.FromSeconds(1);
    _timer1.Tick += timer_Tick1;
    _timer1.Start();     
    // defining the file to show to the user
    string procedure = "procedure1.mp4"
    _media1 = "//10.10.0.1/Procedures/ + procedure;
    ShowVideo(_media1);            
}

// Action done when a tick for timer occur
private void timer_Tick1(object sender, EventArgs e)
{
    // decreasing countdown
    _startingTimer1--;
    // calculate and show the timer (countdown)
    TimeSpan time = TimeSpan.FromSeconds(_startingTimer1);
    tbxTemps1.Text = time.ToString(); 
    // if timer under 0
    if (_startingTimer1 < 0)
    {
        // change background color depending on number
        if (_startingTimer1 % 2 == 0)
        btnTemps1.Background = new SolidColorBrush(Colors.OrangeRed);                
        else
            btnTemps1.Background = new SolidColorBrush(Colors.LightGray);
    }            
}

// show the file to the user
private void ShowVideo(string media)
{
    try
    {
        // define a process to show the file
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        // declare the path to the file
        process.StartInfo.FileName = new Uri(media, UriKind.Absolute).ToString();
        process.StartInfo.UseShellExecute = true;
        // start the process to show the file to the user
        process.Start();
        process.WaitForExit();
    }
    catch
    {
        MessageBox.Show("Could not open the file.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
    }
}

要解决这个问题,线程的使用确实很方便。使用线程调用函数使计时器在主线程中继续,而其他事情在另一个线程中并行完成。为实现这一点,这就是我所做的更改。 我更改了 ShowVideo 方法如下:

    private void ShowVideo(string media)
    {
        try
        {
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            
            process.StartInfo.FileName = new Uri(media, UriKind.Absolute).ToString();
            process.StartInfo.UseShellExecute = true;
            Thread showFile = new Thread(() => process.Start());
            showFile.Start(); // start the Thread
            showFile.Join();
            showFile.WaitForExit();
        }
        catch
        {
            MessageBox.Show("Could not open the file.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
        }
    }