Выход из потока автоматически при закрытии приложения WPF - PullRequest
4 голосов
/ 20 марта 2010

У меня есть главное окно WPF, и одним из его элементов управления является созданный мной пользовательский элемент управления. Этот пользовательский элемент управления является аналоговыми часами и содержит поток, который обновляет часовую, минутную и секундную стрелки. Изначально это был не поток, а событие таймера, которое обновляло часы, минуты и секунды, но я изменил его на поток, потому что приложение выполняет тяжелую работу, когда пользователь нажимает кнопку запуска, а затем часы не обновить, поэтому я изменил его в поток.

Фрагмент кода окна 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>

Моя проблема в том, что когда пользователь выходит из приложения, поток, похоже, продолжает выполняться. Я хотел бы, чтобы поток завершался автоматически при закрытии основных окон.

Фрагмент кода конструктора пользовательского элемента управления:

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

Как я могу автоматически выйти из потока, когда главное окно закрывается, а затем выходит из приложения?

Ответы [ 5 ]

11 голосов
/ 20 марта 2010

Просто установите для свойства IsBackground потока значение true, чтобы оно не мешало завершению процесса.

Thread t = new Thread(...) { IsBackground = true };
1 голос
/ 20 марта 2010

Что ж, одна из основных проблем, с которой вы столкнулись, заключается в том, что вы выполняете бесконечный цикл, который ставит в очередь множество диспетчерских заданий для непрерывного и быстрого обновления часов. Простым решением может быть помещение оператора Thread.Sleep(1000); в цикл, а затем превращение вашего потока в фоновый поток, как предлагает Тейлор.

В любом случае, я немного удивлен, что фоновая работа приведет к сбою обновления таймера. Работать с таким подходом было бы идеальным решением. Возможно, попробуйте DispatcherTimer и посмотрите, сможет ли он обновляться во время фоновой работы.

0 голосов
/ 09 апреля 2010

Я знаю, что вы решили свою проблему, но, поскольку у меня возникла похожая проблема, связанная с запущенным потоком и правильным выходом из приложения, я решил поделиться тем, как я решил свою проблему.

Я закончил тем, что обогнул используемую вами модель диспетчера / потока и вместо этого решил использовать класс BackgroundWorker (System.ComponentModel.BackgroundWorker). Это был простой 4-х шаговый процесс:

  1. создать приватного пользователя для хранения BackgroundWorker
  2. назначить обработчик событий BackgroundWorker.DoWork в ctor
  3. определяет метод обработчика событий DoWork
  4. вызовите _myBackgroundWorker.RunWorkAsync (), когда я хотел запустить фактическую работу.

Подробные сведения об использовании BackgroundWorker, встроенного в , в этой статье об использовании Dispatcher в WPF .

Надеюсь, это кому-нибудь поможет ...

0 голосов
/ 30 марта 2010

Наконец, я смешал два решения: RandomEngy и Taylor, но оно работало не совсем хорошо (приложение не было успешно завершено), поэтому я решил объединить их с другим решением в потоке:

wpf отменить фоновый работник при выходе из приложения

Я приложение главного окна, из XAML я установил свойство ShutdownMode своего приложения в OnMainWindowClose, как сказал Томас в своем комментарии.

Спасибо!

0 голосов
/ 20 марта 2010

Может быть использовать DependecyProperty в вашей модели часов http://www.wpftutorial.net/HowToCreateADepProp.html DependecyProperty работает быстрее, чем интерфейс INotifyPropertyChanget, поэтому, возможно, он вам подойдет http://blog.lexique -du-net.com / index.php? Post / 2010/02/24 / DependencyProperties-or-INotifyPropertyChanged

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...