2017-01-04 2 views
1

У меня есть класс, используя следующий код. Дополнительно я использую другой класс для проверки доступности моего сетевого подключения. Этот класс предоставляет событие для этого, которое я использую для запуска и остановки таймера.Асинхронное и диспетчерское объяснение

Если событие увольняют, я всегда получаю сообщение об ошибке

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

public class ViewModel : BindableBase 
{ 

    private DispatcherTimer timerUpdate = null; 

    public ViewModel() 
    { 
     NetworkAvailabilty.Instance.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged; 

     timerUpdate = new DispatcherTimer(); 
     timerUpdate.Interval = TimeSpan.FromMinutes(15); 
     timerUpdate.Tick += timerUpdate_Tick; 

     if (NetworkAvailabilty.Instance.IsNetworkAvailable) 
     { 
      timerUpdate.Start(); 
     } 
    } 

    private void timerUpdate_Tick(object sender, object e) 
    { 
     // do something 
    } 

    public void OnNetworkAvailabilityChanged(object source, EventArgs e) 
    { 
     if (NetworkAvailabilty.Instance.IsNetworkAvailable) 
     { 
      timerUpdate.Start();     
     } 
     else 
     { 
      timerUpdate.Stop(); 
     }  
    } 
} 

Таким образом, после некоторых исследований я установил с использованием следующего кода:

public void OnNetworkAvailabilityChanged(object source, EventArgs e) 
    { 
     if (NetworkAvailabilty.Instance.IsNetworkAvailable) 
     { 
      Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, 
      () => 
      { 
       timerUpdate.Start(); 
      }); 

     } 
     else 
     { 
      Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, 
      () => 
      { 
       timerUpdate.Stop(); 
      });     
     }    
    } 

Но что же такое d, что проблема и как эта часть кода предотвращает это сообщение об ошибке? Даже здесь Visual Studio говорит мне, что я должен рассмотреть возможность использования ждать перед Windows.ApplicationModel .....

ответ

4

Но что стоит за этим вопросом

DispatcherTimer создается в потоке пользовательского интерфейса, и это то, что называется «поточно-аффинным» объектом (как и большинство компонентов пользовательского интерфейса). Это означает, что он «связывается» с его потоком пользовательского интерфейса и теперь принадлежит ему.

NetworkAvailabilty не является компонентом пользовательского интерфейса, и он всегда вызывает событие NetworkAvailabilityChanged в потоке пула потоков.

Таким образом, OnNetworkAvailabilityChanged работает в потоке пула потоков и пытается получить доступ к DispatcherTimer, который связан с потоком пользовательского интерфейса. Это то, что вызывает исключение:

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

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

Как эта часть кода предотвращает это сообщение об ошибке?

RunAsync выполняет свой делегат в области пользовательского интерфейса.

Лично я предпочитаю использовать SynchronizationContext вместо Dispatcher/CoreDispatcher. Если вы используете диспетчер, вы должны позвонить await и сделать OnNetworkAvailabilityChanged обработчиком событий async void.

Смежные вопросы