Тупик при вызове потока пользовательского интерфейса из рабочего потока

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

return (ucAvancementTrtFamille)mInterfaceTraitement.Invoke(d, new object[] { psFamille });

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

Есть ли способ:

  • Посмотрите, какой поток я пытаюсь вызвать?
  • посмотреть, что на самом деле делает поток?

На изображении ниже показано, что рабочий поток (ID 3732) заблокирован в строке Invoke, а MainThread не работает в основной функции приложения.

alt text

Изменить: Вот стопка основного потока:

alt text

Edit2: Вообще-то, я приостановил программу во второй раз, и вот что выглядит в стеке:

alt text

Edit3: Обходное решение найдено

Наконец-то я нашел обходное решение. Проблема, по-видимому, связана с расой асинхронной оболочки состояние выпуск. Обходной путь - использовать BeginInvoke и ждать его с таймаутом. Когда он истечет, вызовите его снова и запустите, пока он не вернется. Большую часть времени он фактически работает во втором вызове.

IAsyncResult ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille });
            while (!ar.AsyncWaitHandle.WaitOne(3000, false))
            {
                ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille });
            }
            // Async call has returned - get response
            ucAvancementTrtFamille mucAvancementTrtFamille = (ucAvancementTrtFamille)mInterfaceTraitement.EndInvoke(ar);

Это не очень, но это единственное решение, которое я нашел.

Ответ 1

Основной поток не выглядит бездействующим. Ваш снимок экрана показывает текущее местоположение на ECM.Program.Main. Это не может быть правильно, если он неактивен, то он находится внутри Application.Run(), перекачивая контур сообщения. Это необходимо для завершения Invoke().

Дважды щелкните основной поток и перейдите в окно "Стек вызовов", чтобы узнать, что он действительно делает.

Ответ 2

Пробовали ли вы использовать BeginInvoke вместо Invoke? BeginInvoke является асинхронным.

Ответ 3

Вы правы. Основной поток - это точка входа в приложение, которое обычно является местом вызова Application.Run, который получает цикл сообщений. Таким образом, это должен быть поток пользовательского интерфейса, если вы не сделали что-то необычное в отношении цикла сообщений, который маловероятен.

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

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

Ответ 4

Вместо этого вы пытались использовать BackgroundWorker. Если вы его используете, это сэкономит вам много. Вызовы Invoke и InvokeRequired.
Я считаю, что если вы создадите новый поток и запустите его, вы увидите, что у вас не будет тупика. Я попробую найти старый код и разместить его здесь.

Ответ 5

Используете ли вы Visual Studio 2008? Если да, вы должны попробовать с Visual Studio 2010. Это известная ошибка.

Удачи!