WPF应用程序关闭时自动退出线程

时间:2022-08-03 05:06:43

I have a main WPF window and one of its controls is a user control that I have created. This user control is an analog clock and contains a thread that update hour, minute and second hands. Initially it wasn't a thread, it was a timer event that updated the hour, minutes and seconds but I have changed it to a thread because the application does some hard work when the user press a start button and then the clock wouldn't update so I changed it to a thread.

我有一个主WPF窗口,其中一个控件是我创建的用户控件。此用户控件是模拟时钟,包含更新时针,分针和秒针的线程。最初它不是一个线程,它是一个更新小时,分钟和秒的计时器事件,但我已将其更改为一个线程,因为当用户按下一个开始按钮然后时钟不会时,应用程序会做一些艰苦的工作更新所以我把它改成了一个线程。

Code snippet of WPF window:

WPF窗口的代码片段:

     <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
xmlns:local="clr-namespace:GParts"
       xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes
       assembly=PresentationFramework.Aero"            
       xmlns:UC="clr-namespace:GParts.UserControls"
       x:Class="GParts.WinMain"
       Title="GParts"    
       WindowState="Maximized"
       Closing="Window_Closing"    
       Icon="/Resources/Calendar-clock.png"
       x:Name="WMain"
     >
     <...>
          <!-- this is my user control -->
          <UC:AnalogClock Grid.Row="1" x:Name="AnalogClock" Background="Transparent"
           Margin="0" Height="Auto" Width="Auto"/>
     <...>
     </Window>

My problem is that when the user exits the application then the thread seems to continue executing. I would like the thread to finish automatically when the main windows closes.

我的问题是,当用户退出应用程序时,线程似乎继续执行。我希望线程在主窗口关闭时自动完成。

Code snippet of user control constructor:

用户控件构造函数的代码片段:

namespace GParts.UserControls
{
/// <summary>
/// Lógica de interacción para AnalogClock.xaml
/// </summary>
public partial class AnalogClock : UserControl
{
    System.Timers.Timer timer = new System.Timers.Timer(1000);

    public AnalogClock()
    {
        InitializeComponent();

        MDCalendar mdCalendar = new MDCalendar();
        DateTime date = DateTime.Now;
        TimeZone time = TimeZone.CurrentTimeZone;
        TimeSpan difference = time.GetUtcOffset(date);
        uint currentTime = mdCalendar.Time() + (uint)difference.TotalSeconds;

        christianityCalendar.Content = mdCalendar.Date("d/e/Z", currentTime, false);

        // this was before implementing thread
        //timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        //timer.Enabled = true;

        // The Work to perform 
        ThreadStart start = delegate()
        {

            // With this condition the thread exits when main window closes but
            // despite of this it seems like the thread continues executing after
            // exiting application because in task manager cpu is very  busy
            // 
            while ((this.IsInitialized) && 
                   (this.Dispatcher.HasShutdownFinished== false))
           {

            this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
            {
                DateTime hora = DateTime.Now;

                secondHand.Angle = hora.Second * 6;
                minuteHand.Angle = hora.Minute * 6;
                hourHand.Angle = (hora.Hour * 30) + (hora.Minute * 0.5);

                DigitalClock.CurrentTime = hora;
            }));
        }
            Console.Write("Quit ok");
        };

        // Create the thread and kick it started!
        new Thread(start).Start();
    }

    // this was before implementing thread
    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {

        this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
        {
            DateTime hora = DateTime.Now;

            secondHand.Angle = hora.Second * 6;
            minuteHand.Angle = hora.Minute * 6;
            hourHand.Angle = (hora.Hour * 30) + (hora.Minute * 0.5);

            DigitalClock.CurrentTime = hora;
        }));
    }
 } // end class
 } // end namespace

How can I automatically exit from the thread when the main window closes and then the application exits?

当主窗口关闭然后应用程序退出时,如何自动退出线程?

5 个解决方案

#1


11  

Just set the IsBackground property of the Thread to true so it doesn't prevent the process from terminating.

只需将Thread的IsBackground属性设置为true,这样就不会阻止进程终止。

Thread t = new Thread(...) { IsBackground = true };

#2


1  

Well, one major problem you have is you seem to be running an infinite loop that queues a lot of dispatcher jobs to update your clock, continuously and quickly. An easy fix might be to put a Thread.Sleep(1000); statement in the loop, then making your thread a background thread as Taylor suggests.

好吧,你遇到的一个主要问题是你似乎正在运行一个无限循环,它会让很多调度员工作排队,以便连续快速地更新你的时钟。一个简单的修复可能是放一个Thread.Sleep(1000);循环中的语句,然后使你的线程成为泰勒建议的后台线程。

Anyway, I'm a little surprised that background work would cause a Timer to fail to update. Getting that approach working would be the ideal solution. Maybe try out DispatcherTimer and see if that can do updates while background work is going on.

无论如何,我有点惊讶,后台工作会导致Timer无法更新。使该方法有效将是理想的解决方案。也许尝试DispatcherTimer,看看是否可以在后台工作进行时进行更新。

#3


0  

May be use DependecyProperty in Your clock-model http://www.wpftutorial.net/HowToCreateADepProp.html DependecyProperty is faster than INotifyPropertyChanget interface, so maybe it's will good for you http://blog.lexique-du-net.com/index.php?post/2010/02/24/DependencyProperties-or-INotifyPropertyChanged

可以在你的时钟模型中使用DependecyProperty http://www.wpftutorial.net/HowToCreateADepProp.html DependecyProperty比INotifyPropertyChanget界面更快,所以也许它对你有好处http://blog.lexique-du-net.com/的index.php?交/ 2010/02/24 / DependencyProperties - 或 - INotifyPropertyChanged的

#4


0  

Finally I mixed two solutions, RandomEngy and Taylor but it wasn't working quit well (application wasn't exit successfully) so I decided to combine them with another one solution in the thread:

最后我混合了两个解决方案,RandomEngy和Taylor,但它没有正常工作(应用程序没有成功退出)所以我决定将它们与线程中的另一个解决方案结合起来:

wpf cancel backgroundworker on application exits

wpf在应用程序退出时取消后台工作程序

I main window application, from XAML I set the ShutdownMode property of my application to OnMainWindowClose as Thomas said in his comment.

我是主窗口应用程序,从XAML我将我的应用程序的ShutdownMode属性设置为OnMainWindowClose,正如Thomas在评论中所说。

Thanks!

#5


0  

I know you solved your problem, but as I was having a similar issue regarding a running thread and exiting the application correctly, I thought I'd share how I solved my problem.

我知道你解决了你的问题,但由于我遇到了关于正在运行的线程和正确退出应用程序的类似问题,我想我会分享我是如何解决我的问题的。

I ended up skirting the dispatcher/thread model you used and instead opted to use the BackgroundWorker class (System.ComponentModel.BackgroundWorker). It was a simple 4 step process:

我最终绕开了您使用的调度程序/线程模型,而是选择使用BackgroundWorker类(System.ComponentModel.BackgroundWorker)。这是一个简单的4步过程:

  1. create a private member to hold the BackgroundWorker
  2. 创建一个私有成员来保存BackgroundWorker

  3. assign the BackgroundWorker.DoWork event handler in the ctor
  4. 在ctor中分配BackgroundWorker.DoWork事件处理程序

  5. define the DoWork event handler method
  6. 定义DoWork事件处理程序方法

  7. call _myBackgroundWorker.RunWorkAsync() when I wanted to fire off the actual work.
  8. 当我想要开始实际工作时调用_myBackgroundWorker.RunWorkAsync()。

There are details on using BackgroundWorker embedded in this article about using the Dispatcher in WPF.

有关使用本文中嵌入的BackgroundWorker有关在WPF中使用Dispatcher的详细信息。

Hope it helps someone...

希望它有助于某人......

#1


11  

Just set the IsBackground property of the Thread to true so it doesn't prevent the process from terminating.

只需将Thread的IsBackground属性设置为true,这样就不会阻止进程终止。

Thread t = new Thread(...) { IsBackground = true };

#2


1  

Well, one major problem you have is you seem to be running an infinite loop that queues a lot of dispatcher jobs to update your clock, continuously and quickly. An easy fix might be to put a Thread.Sleep(1000); statement in the loop, then making your thread a background thread as Taylor suggests.

好吧,你遇到的一个主要问题是你似乎正在运行一个无限循环,它会让很多调度员工作排队,以便连续快速地更新你的时钟。一个简单的修复可能是放一个Thread.Sleep(1000);循环中的语句,然后使你的线程成为泰勒建议的后台线程。

Anyway, I'm a little surprised that background work would cause a Timer to fail to update. Getting that approach working would be the ideal solution. Maybe try out DispatcherTimer and see if that can do updates while background work is going on.

无论如何,我有点惊讶,后台工作会导致Timer无法更新。使该方法有效将是理想的解决方案。也许尝试DispatcherTimer,看看是否可以在后台工作进行时进行更新。

#3


0  

May be use DependecyProperty in Your clock-model http://www.wpftutorial.net/HowToCreateADepProp.html DependecyProperty is faster than INotifyPropertyChanget interface, so maybe it's will good for you http://blog.lexique-du-net.com/index.php?post/2010/02/24/DependencyProperties-or-INotifyPropertyChanged

可以在你的时钟模型中使用DependecyProperty http://www.wpftutorial.net/HowToCreateADepProp.html DependecyProperty比INotifyPropertyChanget界面更快,所以也许它对你有好处http://blog.lexique-du-net.com/的index.php?交/ 2010/02/24 / DependencyProperties - 或 - INotifyPropertyChanged的

#4


0  

Finally I mixed two solutions, RandomEngy and Taylor but it wasn't working quit well (application wasn't exit successfully) so I decided to combine them with another one solution in the thread:

最后我混合了两个解决方案,RandomEngy和Taylor,但它没有正常工作(应用程序没有成功退出)所以我决定将它们与线程中的另一个解决方案结合起来:

wpf cancel backgroundworker on application exits

wpf在应用程序退出时取消后台工作程序

I main window application, from XAML I set the ShutdownMode property of my application to OnMainWindowClose as Thomas said in his comment.

我是主窗口应用程序,从XAML我将我的应用程序的ShutdownMode属性设置为OnMainWindowClose,正如Thomas在评论中所说。

Thanks!

#5


0  

I know you solved your problem, but as I was having a similar issue regarding a running thread and exiting the application correctly, I thought I'd share how I solved my problem.

我知道你解决了你的问题,但由于我遇到了关于正在运行的线程和正确退出应用程序的类似问题,我想我会分享我是如何解决我的问题的。

I ended up skirting the dispatcher/thread model you used and instead opted to use the BackgroundWorker class (System.ComponentModel.BackgroundWorker). It was a simple 4 step process:

我最终绕开了您使用的调度程序/线程模型,而是选择使用BackgroundWorker类(System.ComponentModel.BackgroundWorker)。这是一个简单的4步过程:

  1. create a private member to hold the BackgroundWorker
  2. 创建一个私有成员来保存BackgroundWorker

  3. assign the BackgroundWorker.DoWork event handler in the ctor
  4. 在ctor中分配BackgroundWorker.DoWork事件处理程序

  5. define the DoWork event handler method
  6. 定义DoWork事件处理程序方法

  7. call _myBackgroundWorker.RunWorkAsync() when I wanted to fire off the actual work.
  8. 当我想要开始实际工作时调用_myBackgroundWorker.RunWorkAsync()。

There are details on using BackgroundWorker embedded in this article about using the Dispatcher in WPF.

有关使用本文中嵌入的BackgroundWorker有关在WPF中使用Dispatcher的详细信息。

Hope it helps someone...

希望它有助于某人......