WPF Threading - может кто-нибудь объяснить, что здесь происходит?

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: следующий код я бы никогда не использовал в реальном приложении. Я наткнулся на эту проблему и хотел бы знать, что происходит под капотами.

Предположим, что по какой-то безумной причине у нас был следующий код ...

using (System.Net.WebClient webClient = new System.Net.WebClient())
{
    bool done = false;
    webClient.UploadFileCompleted += (s, e) => done = true;

    string uploadUri = "ftp://www.notarealurl.com/";
    string file = @"temp.txt";

    webClient.UploadFileAsync(
        new Uri("ftp://www.notarealurl.com/"), "temp.txt");

    while (!done)
    {
        System.Threading.Thread.Sleep(100);
    }
}

Этот код работает должным образом в простом консольном приложении. Однако переместите его в приложение WPF, и оно никогда не выйдет из цикла while. Это через меня в течение некоторого времени, пока мне не пришло в голову, что это может быть проблема с событиями, которые отбрасываются в насосе сообщений и поэтому не обрабатываются. Чтобы проверить это, я изменил цикл «while» следующим образом ...

while (!done)
{
    System.Threading.Thread.Sleep(100);

    // Processes all messages currently in the message queue
    Dispatcher.Invoke(
        DispatcherPriority.Background, new ThreadStart(delegate { }));
}

Конечно, это исправило это. Итак, к вопросу ...

Что здесь происходит? Когда я запускаю этот код в консольном приложении, обработчик событий выполняется в рабочем потоке. Почему / как он попадает в основной поток в WPF?

Вы делаете эту загрузку в своей ветке пользовательского интерфейса?

Sam Saffron 20.01.2009 03:47

Я в этом примере. Обычно я бы этого не сделал, но я реорганизовал потоковую модель программы и временно поместил ее в поток пользовательского интерфейса, когда столкнулся с этим.

herbrandson 20.01.2009 19:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
2 744
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, что в WPF он пытается поместить все обратные вызовы в поток, из которого они пришли. Это называется «сродством» нити.

I מ WPF (а также в WinForms, Win32 и любой другой библиотеке пользовательского интерфейса, с которой я когда-либо работал) вы можете получить доступ к объекту пользовательского интерфейса только из того же потока, который его создал.

Кроме того, в любой программе Windows с графическим интерфейсом пользователя у вас есть цикл сообщений и отправка сообщений, а в консольном приложении - нет.

Так что, похоже, либо

  1. WebClient обнаруживает, что он работает в приложении с графическим интерфейсом пользователя, и пытается помочь, вызывая события в том же потоке, который его активировал.

или же

  1. WebClient использует внутреннюю диспетчеризацию сообщений и возвращается к рабочим потокам только в консольных приложениях.
In WPF you can only access a UI object from the same thread that created it. Это неверно для фиксируемых элементов пользовательского интерфейса.
GETah 06.03.2012 16:24
Ответ принят как подходящий

Хорошо, я немного декомпилировал с помощью Reflector и разобрался, что происходит под капотами. Веб-клиент использует класс SynchronizationContext для обработки обратных вызовов в исходный поток. Я не был знаком с классом SynchronizationContext, но здесь есть очень хорошая статья об этом ...

http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

Другие вопросы по теме