Тупик при вызове потока пользовательского интерфейса из рабочего потока - PullRequest
11 голосов
/ 21 сентября 2010

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

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

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

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

  1. видите, какую нить я на самом деле пытаюсь вызвать?
  2. видите, что на самом деле делает этот поток?

На изображении ниже мы видим, что рабочий поток (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);

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

Ответы [ 5 ]

5 голосов
/ 21 сентября 2010

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

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

2 голосов
/ 21 сентября 2010

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

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

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

2 голосов
/ 21 сентября 2010

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

0 голосов
/ 22 сентября 2010

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

Удачи!

0 голосов
/ 21 сентября 2010

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

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