2013-08-16 2 views
0

Я пишу небольшое приложение WPF для тестирования кода SignalR. Все работает с того, что я написал, но я наткнулся на то, о чем я не уверен.SignalR WPF StateChange Issues

Я создал обработчик событий для события HubConnectionStateChanged;

_hub.StateChanged += (change) => 
{ 
    Console.WriteLine("hubConnection.StateChanged {0} => {1}", change.OldState, change.NewState); 

    if (change.NewState == ConnectionState.Connecting) 
    { 
     statusCallBack callBack = new statusCallBack(UpdateStatus); 
     this.Dispatcher.Invoke(callBack, "hubConnection.StateChanged"); 
    } 
    if (change.NewState == ConnectionState.Connected) 
    { 
     Console.WriteLine("hello"); 
     statusCallBack callBack = new statusCallBack(UpdateStatus); 
     this.Dispatcher.Invoke(callBack, "hubConnection.StateChanged"); 
    } 
}; 

С моим методом Делегата statusCallBack и метод бытия;

delegate void statusCallBack(string msg); 

private void UpdateStatus(string msg) 
{ 
    if (this.Dispatcher.CheckAccess() == true) 
    {     
     this.tbStatus.AppendText(Environment.NewLine + DateTime.Now.ToLongTimeString() + " --- " + msg); 
     this.tbStatus.CaretIndex = this.tbStatus.Text.Length; 
     this.tbStatus.ScrollToEnd(); 
    } 
} 

Теперь я, вероятно, отсутствует что-то действительно очевидное здесь, но когда в StateChanged обработчика я проверяю для ConnectionState.Connecting и вывода сообщения на мой ярлык он работает отлично.

Затем, когда состояние SignalR HubConnection затем изменяется на ConnectionState.Connected, и я пытаюсь вызвать делегата, приложение WPF просто блокируется.

Он будет выводить на консоль в порядке и проверяет, есть ли change.NewState == ConnectionState.Connected, а затем выводит «привет» на консоль, но затем просто зависает.

Если я отлаживаю приложение, когда оно попадает в оператор Connected if, объект change.NewState и change.OldState имеют сообщение об ошибке ниже.

enter image description here

View larger image here.

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

Даже если я прокомментирую начальный оператор if для проверки на Connecting, он все равно замерзнет, ​​когда Connected.

ответ

2

Это обычная проблема взаимоблокировки при обращении к пользовательскому интерфейсу от события.

Используйте Dispatcher.BeginInvoke, а не Invoke.

Как указано в this темы:

При использовании Dispatcher.BeginInvoke это означает, что он планирует ее данное действие для выполнения в потоке пользовательского интерфейса на более поздний момент времени, , а затем возвращает управление разрешить текущему потоку продолжить выполнение . Вызов блокирует вызывающего абонента до завершения запланированного действия .

В качестве побочного примечание: MVVM Light имеет очень полезный помощник под названием DispatcherHelper, который не совместим только с практически все (WPF, WinRT, SL, и т.д.), но очень прост в использовании. Это поможет вам автоматически отправлять вызовы обратно в пользовательский интерфейс. Если ничего другого, может быть полезно использовать пакет NUGet JUST для этой функции.

+0

Большое спасибо за это. Теперь я могу продолжить свою жизнь: P Я проверю MVVM Light. –

+0

да! в случае ошибки появляется определенная ошибка. Этот тип CollectionView не поддерживает изменения в SourceCollection из потока, отличного от потока Dispatcher.' 'несмотря на' System.Threading.Thread.CurrentThread == System.Windows.Threading.Dispatcher.CurrentDispatcher.Thread' является истинным –

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