Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does first BeginInvoke fail, when second try succeeds? Message loop not responsive?
    primarykey
    data
    text
    <p>I have an <code>EventHandler</code> on a custom <code>Control</code>, which is called from a background thread and invalidates the control. To do this, I use <code>Invoke</code> as follows:</p> <pre class="lang-cpp prettyprint-override"><code>void Foo::handleProgressChanged(Object^ sender, EventArgs^ args) { if (InvokeRequired) { Invoke(gcnew EventHandler(this, &amp;Foo::handleProgressChanged), sender, args); return; } this-&gt;UpdateProgress(); this-&gt;Invalidate(true); } </code></pre> <p><strong>Under some rare conditions the call to <code>Invoke</code> causes a deadlock</strong> although the message loop should be pumping. The callstack of the main thread is:</p> <pre class="lang-none prettyprint-override"><code>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 ... </code></pre> <p>I tried to switch to <code>BeginInvoke</code>, but the passed delegate was never executed. I found a workaround that is far from optimal and that I regard as an evil hack: If I call <code>BeginInvoke</code> twice, the second call has the expected effect:</p> <pre class="lang-cpp prettyprint-override"><code>void Foo::handleProgressChanged(Object^ sender, EventArgs^ args) { if (InvokeRequired) { IAsyncResult^ r = BeginInvoke(gcnew EventHandler(this, &amp;Foo::handleProgressChanged), sender, args); if (!r-&gt;AsyncWaitHandle-&gt;WaitOne(1000, false)) { r = BeginInvoke(gcnew EventHandler(this, &amp;Foo::handleProgressChanged), sender, args); } } this-&gt;UpdateProgress(); this-&gt;Invalidate(true); } </code></pre> <p>I am not able to boil the code down to a small self-contained example but my specific question are:</p> <ul> <li><strong>Under which conditions can <code>Invoke</code> block the background thread, when the UI thread is idle?</strong></li> <li><strong>Why is the second call to <code>BeginInvoke</code> successful, while the first one is not?</strong></li> </ul> <p>I'm using .NET Framework 2 and C++/CLI, however I suppose the problem is not language-specific.</p> <p><strong>Edit:</strong></p> <p>To make it clearer: the original approach works most of the time. The first events in a session are handled as expected. But later, especially when the events occur frequently, it runs into the deadlock.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload