Попытка обновить пользовательский интерфейс из фонового потока: почему он иногда выбрасывает, а иногда просто ничего не делает? - PullRequest
3 голосов
/ 12 мая 2011

Я заметил в WPF, что при попытке обновить пользовательский интерфейс из фонового потока (я знаю, что вы не должны этого делать - просто поиграть с вещами), что иногда он генерирует исключение InvalidOperationException, а иногда простоничего не делает.Впервые я заметил это, когда неправильно пытался обновить пользовательский интерфейс из фонового потока, запущенного асинхронным вызовом WCF (используя Begin / End, а не модель событий, которая автоматически маршалирует в поток пользовательского интерфейса).

Например,скажем, у меня есть простая форма с кнопкой и флажком.Этот код будет генерировать исключение InvalidOperationException («Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет им.») Каждый раз:

private void button1_Click(object sender, RoutedEventArgs e)
{
    new Thread(() => checkBox1.IsChecked = true).Start();
}

Теперь, примите ту же форму и добавьте стандартную службу болотассылка на простой сервис WCF где-то.Затем попробуйте это:

private void button1_Click(object sender, RoutedEventArgs e)
{
    var client = new MyServiceClient();
    //Note the use of Begin/End as opposed to the eventing model - Callback
    //will not be called on the UI thread, but a worker thread. I have
    //verified this through the debugger thread list and by checking the 
    //result of Dispatcher.CheckAccess() in the callback.
    client.BeginMyServiceMethod("MyArgument", Callback, null);
}

private void Callback(IAsyncResult result)
{
    //If I call Dispatcher.CheckAccess() here, it returns false,
    //but if I call Dispatcher.VerifyAccess() it does not throw!
    checkBox1.IsChecked = true;  // no exception, no effect
}

Насколько я понимаю, вызов Dispatcher.VerifyAccess () в этом методе обратного вызова должен быть сгенерирован, как и при попытке что-либо манипулировать на checkBox1.Вместо этого ничего не происходит - флажок в пользовательском интерфейсе не становится установленным, и никакое исключение не выдается.Кто-нибудь знает, почему это так?

Ответы [ 2 ]

1 голос
/ 13 мая 2011

Возможно ли, что код Framework, который выполняет вызов метода обратного вызова, поглощает исключения?Введите try/catch в обратном вызове, чтобы увидеть, генерируются ли исключения.Если это так, то вы знаете, что Framework поглощает исключения.

0 голосов
/ 12 мая 2011

Как правило, большинство сред с графическим интерфейсом не поддерживают (и даже не поощряют) манипулирование виджетами из разных потоков. Обычно есть только 1 поток, обрабатывающий данный графический интерфейс. Большинство наборов GUI предоставляют механизм, с помощью которого вы можете вызывать «задачу» в потоке GUI и, таким образом, безопасно управлять виджетами. Это будет упражнение в скуке, чтобы создать новое задание для каждого тонка виджета, который вы хотите сделать, но на самом деле альтернативы нет.

Для C # и wpf (прошло немного времени), я считаю, что механизм вращается вокруг:

widget.Dispatcher.BeginInvoke(delegate, args[])

Таким образом, для каждой настройки виджета, которую вы хотите сделать, вы создаете делегата для выполнения этой настройки, а затем вызываете его через диспетчер виджетов (объект, который обрабатывает отправку событий в потоке графического интерфейса виджетов).

Ссылки

BeginInvoke

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...