Rob Calhoun Posted August 7, 2009 Report Share Posted August 7, 2009 I encountered this bizarre and performance-destroying behavior yesterday so I thought I should write up some notes on it. In our application we call various Microsoft components (Active Data Objects, WinHTTP, MSXML) to do tasks that aren't build-in to LabView (database connectivity, http and xpath queries, respectively.) We use the Automation (ActiveX) functions for this. When we expect to call these routines in parallel, their wrappers are set for re-entrant execution. I was running a process that does a lot of downloading via WinHTTP in one thread while doing a lot of opening and closing of databases in another. I was getting extremely poor performance. A little debugging isolated the problem to a block on the Automation Open function (on an ADO object!) while WinHTTP was doing a synchronous download. Adding more parallel downloads makes the problem worse; I have no trouble firing off 5 WinHTTP downloads in parallel, but doing so almost completely lobotomizes LabView. Click the run button with five WinHTTP clones chomping away at big files and even the simplest routines (see two-plus-two.png) get completely stuck. The solution is simple: enable asynchronous downloads. From the WinHttpRequest documentation. "The main advantage to using WinHTTP asynchronously in script is that the Send method returns immediately. The request is prepared and sent by a worker thread. This enables your application to do other things while it is waiting for the response. " We had set it to synchronous because a) it was the default and b) we were running it in a clone anyway and didn't really want the clone to do anything other than wait for the download to complete. What I did not realize is that when Microsoft says "[t]his enables your application to do other things while it is waiting for the response", they are not kidding! The WinHttpRequest.Send method apparently has deep ties into the depths of the Windows execution system and you REALLY cannot do other things while it is running. The strangest part of the whole business is that while you can set up an ActiveX event to catch the completion notice, if you don't mind you VI (as opposed to your entire application) to get blocked, the easy way to do a download is to fire off the request with WinHttpRequest.Send (async) and then wait (synchronously) for it to complete or timeout using WinHttpRequest.WaitForResponse. WinHttpRequest.WaitForResponse blocks your VI but it doesn't destroy your world. So in the end this had an easy solution. (And I was really sweating this last night!) This kind of issue, however, is why Jim and I would like to see a nice SSL-capable http client built in to LabView. (see Setting up SSL Web Services). Here is the synchronous (blocking) code. DON'T DO THIS! Here is the non-blocking) code. You can use an ActiveX event if you want to show a progress bar or something, but this will get the job done. -Rob Calhoun blocked! blocking: non-blocking: Quote Link to comment
Rob Calhoun Posted August 7, 2009 Author Report Share Posted August 7, 2009 "Timeout" seems to be ignored by WaitForResponse(), at least with all of the data types I can think of stuffing in there. Quote Link to comment
Rob Calhoun Posted August 7, 2009 Author Report Share Posted August 7, 2009 Whoops, I had disabled asynchronous downloads while testing. With Async set to TRUE again, Timeout does work with WaitForResponse(). I'm using an I32. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.