Thread Dispatcher Sleep в WPF - PullRequest
       4

Thread Dispatcher Sleep в WPF

1 голос
/ 18 декабря 2011

Я пытаюсь создать приложение 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 Ответ

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

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

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

  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;
    }));
...