У меня есть EventHandler
для пользовательского Control
, который вызывается из фонового потока и делает элемент управления недействительным.Для этого я использую Invoke
следующим образом:
void Foo::handleProgressChanged(Object^ sender, EventArgs^ args)
{
if (InvokeRequired)
{
Invoke(gcnew EventHandler(this, &Foo::handleProgressChanged), sender, args);
return;
}
this->UpdateProgress();
this->Invalidate(true);
}
В некоторых редких случаях вызов Invoke
вызывает тупик , хотя цикл сообщений должен работать.Вызов стека основного потока:
ntdll.dll!770c5ca4()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
user32.dll!75e6073f()
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = -1, int pvLoopData = 0) + 0x3c8 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.WinFormsAppContext}) + 0x177 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.ApplicationContext context) + 0x18 bytes
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() Line 768 + 0x9 bytes Basic
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() Line 1444 Basic
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String() commandLine = Nothing) Line 491 + 0x7 bytes Basic
...
Я пытался переключиться на BeginInvoke
, но переданный делегат никогда не выполнялся.Я нашел обходной путь, который далек от оптимального и который я расцениваю как злой взломкод до небольшого автономного примера, но мой конкретный вопрос:
- При каких условиях
Invoke
может блокировать фоновый поток, когда поток пользовательского интерфейса простаивает? - Почему второй вызов
BeginInvoke
успешен, а первый - нет?
Я использую .NET Framework 2 и C ++ / CLIОднако я полагаю, что проблема не зависит от языка.
Редактировать:
Чтобы сделать его более понятным: оригинальный подход работает большую часть времени.Первые события в сеансе обрабатываются как ожидалось.Но позже, особенно когда события происходят часто, он заходит в тупик.