views:

451

answers:

2

I want to call WaitHandle.WaitOne(TimeSpan) in .NET, but I'm on the STA thread and it pumps messages while waiting. For reasons that are beyond the scope of this question, I need to wait without pumping. How can I wait for a WaitHandle to be signaled without pumping messages?

It seems in some scenarios that WaitHandle.WaitOne does not pump messages. But it does sometimes for some messages. See these links for more information on that:

  1. Managed and Unmanaged Threading in Microsoft Windows
  2. Managed blocking
+5  A: 

WaitForSingleObject or WaitForMultipleObjects are non-pumping waits; use p/invoke.

[DllImport("kernel32", SetLastError=true, ExactSpelling=true)]
public static extern Int32 WaitForSingleObject(SafeWaitHandle handle, Int32 milliseconds);

-Oisin

x0n
Thanks. I didn't know you could pass a SafeWaitHandle directly into a P/Invoke method. That's cool. Thanks for the tip.
Andrew Arnott
Yeah, the .NET marshaller "knows" about types that expose an IntPtr (GetDangerousHandle in this case, iirc), so you can just replace that parameter in the signature and let the magic happen ;-)
x0n
For some reason, the limited pumping done by WaitOne() prevents minimized forms from being restored when calling WaitOne() in Form.OnActivated. Took me 2 hours to track that bug down to the WaitOne() call, but thanks to your answer here I could fix it quickly :)Thanks!
Daniel
A: 

WaitHandle.WaitOne(TimeSpan) does not pump windows messages, so it already does what you want. From the documentation (emphasis mine):

Blocks the current thread until the current instance receives a signal, using a TimeSpan to measure the time interval.

To test this, create a new winforms project with a single button and this click handler:

  private void button1_Click(object sender, EventArgs e)
  {
     var waitHandle = new ManualResetEvent(false);
     waitHandle.WaitOne(5000);
  }

Clicking the button results in the form becoming unresponsive (as in, unable to redraw, resize, move) for 5 seconds. It's unresponsive because it is not pumping messages.

Wim Coenen
hey man, he actually **wants** a non-pumping wait (odd, I know, but probably due to reentrancy issues). Read the question again :D
x0n
@x0n: The OP believes that WaitOne pumps messages. I point out that it doesn't. Not sure what you're getting at.
Wim Coenen
wcoenen: I know the MSDN documentation doesn't indicate that it pumps messages, but it does pump *some* messages. At least it does on .NET 4.0, but I think it does in earlier versions as well. It's selective about which messages are pumped during the blocking wait to avoid reentrancy, but it doesn't do it perfectly, which is why I need a wait that doesn't pump *any* messages.
Andrew Arnott