[RESOLVED] Making an async call not async...
OK I'm trying to write a 'developer friendly' wrapper for the Windows API EnumWindows - the problem is that the API uses a callback function that gets invoked on another thread, where as I want my wrapper function to simplify this and make it more useful by working like any other normal synchronous function and just returning a value.
Now if the API just called the callback once that would be fine, as I would just call the API and make the wrapper function wait until it got a signal from the callback function telling it to continue... but the API calls the callback function over 100 times (once for every window handle that exists). The biggest problem is that there is nothing that indicates that any particular call to this callback function is the last one, so my wrapper function has no idea when it is safe to continue and return the list of window handles to the caller.
The only solution I could think of is to do this:
1. The wrapper function calls the API and starts a timer that waits 2 seconds before it raises the Elapsed event. The wrapper function then pauses until it receives a signal (ManualResetEvent)
2. Each time the callback function is raised by the API on a different thread, it stops the timer (so this is before the 2 seconds have elapsed), adds the current window handle that was passed in by the API to the list of handles, then starts the timer again.
3. If the timer reaches its 2 second interval then it is assumed that we are at the end of the windows because otherwise the callback would have stopped the timer. So the timer's Elapsed event handler is what signals the original thread (that the wrapper function is executing on) to continue as we now have a complete list of windows to return.
This works fine and does exactly what I want... but I dont like it.
I dont like forcing the caller to wait an extra 2 seconds after the API has done its last callback but more importantly I dont like assuming that the API will never take longer than 2 seconds between callbacks. In reality on my PC it is never anywhere near that long between callbacks, it is something like 200 miliseconds, but I have no idea how long it would be on a slower PC and I want this to be completely reliable.
So can anyone see a better alternative to this or suggest anything that I could do to make my existing solution more reliable?
Thanks :)
Chris
Re: Making an async call not async...
Anyone got any ideas on this? I posted this question on the MSDN forums as well but as usual just got sarcastic useless replies... http://social.msdn.microsoft.com/For...0-6429f57c4d55
Re: Making an async call not async...
Can't say I can think of something better. Like you, I don't like the solution but the API doesn't seem to allow any other way to do what you want.
Re: Making an async call not async...
Hey Chris, I'm not totally sure I understand your problem but would this help? They seem to be able to get the total number of windows as EnumWindows returns a Bool when it ends which I think you can use to figure out when EnumWindows has finished.
Re: Making an async call not async...
Quote:
Originally Posted by
stlaural
Hey Chris, I'm not totally sure I understand your problem but would
this help? They seem to be able to get the total number of windows as EnumWindows returns a Bool when it ends which I think you can use to figure out when EnumWindows has finished.
Thanks, you are correct that EnumWindows returns a bool but the problem is that it returns it straight away before it has actually enumerated the windows and called the specified callback once for each window it finds. So unless VB6 works differently (ie it blocks until the API has finished calling the callback for each window it found), which I doubt, then that example is not actually going to print the total number of windows found when you first press the button because at that point their TopCount variable would still be 0. I dont have VB6 to test it on to prove either way though.
Re: Making an async call not async...
Quote:
Originally Posted by
ntg
Can't say I can think of something better. Like you, I don't like the solution but the API doesn't seem to allow any other way to do what you want.
Thanks for the confirmation that I'm not missing any obvious solution that would work better. I've tested it on quite a few PCs now and it seems to work fine on each of them but still not completely happy with it... though I'm starting to think there is absolutely no other way I can make it work how I want.
Re: Making an async call not async...
Actually it seems that I have got this all wrong - the call to EnumWindows actually does not return until all of the callbacks have been called :) Which is great and all... but I feel like a douche now and cant figure out how I got it into my head that it was async and called the callbacks after the API had already returned! :D
Re: [RESOLVED] Making an async call not async...
:bigyello: Tunnel vision. Happens to me all the time.
Re: Making an async call not async...
Quote:
Originally Posted by
chris128
Actually it seems that I have got this all wrong - the call to EnumWindows actually does not return until all of the callbacks have been called :) Which is great and all... but I feel like a douche now and cant figure out how I got it into my head that it was async and called the callbacks after the API had already returned! :D
I was just about to post a VB.NET sample that clearly demonstrate that it was not "async" :p
Quote:
Originally Posted by
ntg
:bigyello: Tunnel vision. Happens to me all the time.
Yeah, me too !
Re: [RESOLVED] Making an async call not async...
haha well its nice to know I'm not the only one :P thanks for the responses anyway