如何在不停止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);
}
}