Подтвердить что ты не робот

Использование диспетчера С#

Я создаю клиент чата и не уверен на 100% о том, как использовать dispatcher. Поэтому вопрос в том, что у меня есть метод как таковой:

public void LostConnection()
{
    myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n");
}

Нужно ли обрабатывать утверждение в (myGUI.chatBox... ) с помощью Dispatcher.Invoke? Я ценю любую помощь.

4b9b3361

Ответ 1

В вашем приложении есть основной поток пользовательского интерфейса (обычно ManagedThreadId==1). Как правило, в чат-приложении ваши события появятся на других потоках (либо выделенные сокеты, либо потоки потоков потоков из кода прослушивания). Если вы хотите обновить пользовательский интерфейс от события, которое получает какой-либо другой поток, вы должны использовать диспетчер. Полезным тестом здесь является метод Dispatcher.CheckAccess(), который возвращает true, если код находится в потоке пользовательского интерфейса и false, если в каком-то другом потоке. Типичный вызов выглядит примерно так:

using System.Windows.Threading; // For Dispatcher.

if (Application.Current.Dispatcher.CheckAccess()) {
    network_links.Add(new NetworkLinkVM(link, start_node, end_node));
}
else {
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{
        network_links.Add(new NetworkLinkVM(link, start_node, end_node));
    }));
}

Если вы находитесь в главном окне, вы можете использовать:

Dispatcher.BeginInvoke(...

Если вы находитесь в другом контексте, например, в модели вида, используйте:

Application.Current.Dispatcher.BeginInvoke(  

Invoke vs BeginInvoke
Используйте Invoke, если вы хотите, чтобы текущий поток ожидал, пока поток пользовательского интерфейса обработает код отправки или BeginInvoke, если вы хотите, чтобы текущий поток продолжался, не дожидаясь завершения операции в потоке пользовательского интерфейса.

MessageBox, Диспетчеры и Invoke/BeginInvoke:
Dispatcher.Invoke заблокирует ваш поток до тех пор, пока MessageBox не будет уволен.
Dispatcher.BeginInvoke позволит вашему потоковому коду продолжать выполнение, пока поток пользовательского интерфейса блокирует вызов MessageBox до его отклонения.

CurrentDispatcher vs. Current.Dispatcher!
Будь товаром Dispatcher.CurrentDispatcher, поскольку мое понимание этого - это то, что вернет Диспетчер для текущего потока, а не поток пользовательского интерфейса. Обычно вы интересуетесь диспетчером в потоке пользовательского интерфейса - Application.Current.Dispatcher всегда возвращает это.

Примечание:
Если вы обнаружите, что вам приходится часто проверять диспетчер CheckAccess, полезный вспомогательный метод:

public void DispatchIfNecessary(Action action) {
    if (!Dispatcher.CheckAccess())
        Dispatcher.Invoke(action);
    else
        action.Invoke();
}

Которое можно назвать:

DispatchIfNecessary(() => {
    network_links.Add(new NetworkLinkVM(link, start_node, end_node));
});

Ответ 2

Что-то вроде этого (с моей головы) должно работать:

public void LostConnection() 
{ 
   myGUI.Invoke
      ((MethodInvoker)delegate
   {
      myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
   });
}