Exit thread automatically when WPF application closes
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.
Code snippet of WPF window:
<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?
Just set the IsBackground property of the Thread to true so it doesn't prevent the process from terminating.
Thread t = new Thread(...) { IsBackground = true };
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.
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.
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
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:
wpf cancel backgroundworker on application exits
I main window application, from XAML I set the ShutdownMode property of my application to OnMainWindowClose as Thomas said in his comment.
Thanks!
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:
- create a private member to hold the BackgroundWorker
- assign the BackgroundWorker.DoWork event handler in the ctor
- define the DoWork event handler method
- call _myBackgroundWorker.RunWorkAsync() when I wanted to fire off the actual work.
There are details on using BackgroundWorker embedded in this article about using the Dispatcher in WPF.
Hope it helps someone...
精彩评论