title: COM+ hang when calling a COM object under load
body: <p>We have some COM+ code written in everybody's favourite language(?) -- VB6. This COM+ component calls into a standard COM component written by a 3rd party which performs calls into a SQL Server database. We don't do anything fancy in the COM+ -- nothing more than (this is an example only; we don't really call our functions doStuff :-) ):</p>
  
  <pre><code>Function doStuff
     Dim o As Library.Object
     Set o = New Library.Object
     str = o.DoSomething()
     Set o = Nothing
     doStuff = str
  End Function
  </code></pre>
  
  <p>As a horrendously quick stress test, we've wrapped the call up in a drop-dead simple VBScript that simple creates object, calls method in a loop, sets object to nothing, and repeats this a few times. We then run four of these concurrently within a command prompt.</p>
  
  <p>What we experience is the four COM+ windows stopping dead as if they've blocked each other in some way. Based on the behaviour of the output it looks like the different windows are sharing instances of objects somewhere along the way: for example, the speed at which the output appears between windows syncs between the windows ... so two can be blistering along at speed, whilst the other two spit out a line a second (and when they spit the line out, they do so at the same time).</p>
  
  <p>Then ultimately, all four windows seem to stop dead - within component services, we see the Call Time start to climb (so from the few milliseconds per call, it climbs to 30, 40 seconds). Sometimes dllhost.exe fails and we get a COM Surrogate error dialog appear (at which point the window recovers as a new dllhost is spawned).</p>
  
  <p>There is <em>no</em> activity on the database, so we've ruled out that things are blocking at the database layer. We seem to have achieved better results by setting the COM+ component to "Transactions: disabled", but the hangs don't disappear. Rather than <code>new</code>, we're going to try creating the COM object with <code>CreateObject</code> to see what that does (if anything). Objects are set to Nothing once finished with both in COM+ and at the VBScript layer.</p>
  
  <p>Worth noting that if the 3rd party library is called directly from VBScript (bypassing COM+), no issues occur. Thus it seems as if it's something to do with the way that COM+ interacts with COM objects, but other than fiddling with different settings under the objects properties in Component Services, not sure really what else is happening.</p>
  
  <p>Any suggestions as to what's happening under the hood to cause this? Or settings to tweak?</p>
  
  <p><strong>Extra Info</strong><br>
  In answer to questions in answers:</p>
  
  <ul>
  <li>Global variables are not being used (as per <a href="http://support.microsoft.com/kb/815053" rel="nofollow">http://support.microsoft.com/kb/815053</a> ) </li>
  <li>Unattended Execution and Retain In Memory are set correctly (as per <a href="http://support.microsoft.com/kb/264957" rel="nofollow">http://support.microsoft.com/kb/264957</a> )</li>
  <li>As object is a VB COM+ object, it is running STA so Object Pooling cannot be configured</li>
  </ul>
  
  <p><strong>Further work...</strong>
  It looks like it's a sync issue somewhere deep in COM+ or COM. In our test script, if we add a random delay of 10-50ms on each iteration, the problem disappears. If we have a fixed delay, we lock. Some googling around seems to show that it can be a problem on heavily loaded COM+ with an STA, which is <a href="http://blogs.msdn.com/b/asiatech/archive/2009/09/08/com-application-sometime-hangs-after-moving-to-windows-2003-sp2.aspx" rel="nofollow">documented here on an MS blog</a>. It'd be nice to go back to a Server 2000 box or a Server 2003 SP1 box: that might have to be the next thing to see...</p>