Thread Dispatcher Sleep в WPF

Я пытаюсь создать приложение Kinect + WPF. Часть Kinect работает отлично; Теперь я хочу создать метод, чтобы проверить, простаивает ли страница (ни один пользователь не взаимодействует с программой в течение определенного периода времени). Если он не используется в течение 5 секунд, экран будет заблокирован. Это алгоритм:

  1. Начать поток (мне нужно использовать Dispatcher, поскольку поток должен изменять элементы WPF)
  2. Проверьте, использует ли пользователь. Если нет, то увеличьте счетчик на 1.
  3. Если счет == 9 (что означает, что прошло уже 5 секунд), заблокируйте экран и снова установите для счетчика значение 0.
  4. Спи 500 миллисекунд.
  5. Повторите шаг 2-4

Это мой код Метод startLockHandler вызывается при запуске приложения.

 public void startLockHandler()
 {
     Application.Current.Dispatcher.BeginInvoke(new ThreadStart(() => lockHandler()), null);
 }

 public void lockHandler()
    {
        while (true)
        {
            if (myState.isSkeletonTracked == false) //if skeleton is no longer tracked 
            {
                if (myState.ActionAllowed == true) //if the page is not in transition
                {
                    lockCount++;

                    if (lockCount >= 10)
                    {
                        lockCount = 0;

                        myState.ActionAllowed = false;

                        //LOCKING MECHANISM INSERTED HERE. NEED TO MODIFY SOME WPF ELEMENTS
                        myState.ActionAllowed = true;
                    }
                }
            }

            else
            {
                lockCount = 0;
            }
            Console.WriteLine("lockHandler: THREAD SLEEP CALLED");
            Thread.Sleep ( 500 );

        }//end while
    }//end method lockHandler 

Когда я запускаю приложение, оно зависает сразу после его запуска. Мне кажется, что Thread.Sleep (500) инструктирует основной поток спать (пожалуйста, исправьте меня, если я ошибаюсь). У меня вопрос, как я могу указать, какую нить нужно усыпить? Кстати, я не эксперт в C#, а новичок в Threading:(

Спасибо за ваше внимание и, надеюсь, вы можете помочь мне:)

1 ответ

Решение
  1. Dispatcher.BeginInvoke() не создает новый поток, он просто выполняет lockHandler() в основном потоке графического интерфейса. Тот факт, что вы проходите ThreadStart делегат здесь ничего особенного не значит.

  2. Thread.Sleep() помещает в спящий поток, который его вызвал, то есть основной поток GUI в вашем случае. Для управления выполнением одной команды из другой следует использовать примитивы синхронизации (ManualResetEvent, AutoResetEvent, Mutex, Semaphore, так далее).

  3. Вы не должны получать доступ к / изменять пользовательский интерфейс напрямую из другого потока, вы должны вызвать Invoke или же BeginInvokeDispatcher методы из вторичного потока (не потока GUI), чтобы гарантировать, что весь связанный с UI код выполняется из потока, который создал элементы UI.

  4. Вам действительно не нужен вторичный поток с выделенным Dispatcher экземпляр для вашего случая.

Минимальная модификация, в которой как минимум будет использоваться отдельный поток:

var thread = new Thread(lockHandler);
thread.Start();

Помните, что вам также необходимо реализовать способ остановки вторичного потока, иначе это может помешать вашему приложению закрываться и выгружаться из памяти. Quck и (очень) грязное решение будет пометить этот поток как фоновый поток: thread.IsBackground = true,

Обновить

Пример изменения пользовательского интерфейса из вторичного потока:

Application.Current.Dispatcher.BeginInvoke(new Action(
    () =>
    {
         // access UI elements here, for example
         myState.ActionAllowed = false;
    }));
Другие вопросы по тегам