PRB: Blocking Occurs When Calling VB ActiveX EXE from ASP

ID: Q201014


The information in this article applies to:


SYMPTOMS

When you create an ActiveX EXE component under Active Server Pages (ASP) in page scope only, all requests to the component are serialized to a single thread and blocking occurs.


CAUSE

When you use the apartment threading model to create your Visual Basic ActiveX EXE Component, all requests to the same Visual Basic ActiveX EXE Component are serialized.

If an object running in a single-threaded apartment (STA) is called concurrently by multiple clients (regardless of their threading model), COM synchronizes access to the object by posting window messages to the component's message queue. As a result, the object only receives one call each time it retrieves and dispatches a COM-related message.

While this interference implies some performance penalty, it allows applications that support different threading models to work together. Thus, all possible combinations of client and out-of-process component interoperability are supported.


RESOLUTION

By default, your Visual Basic EXE Instancing value is set to MultiUse. Therefore, only one object is created using the single-threaded apartment (STA) model. In Visual Basic, you are unable to mark your component's threading model to either Free or Both to allow multithreading.

However, you can achieve concurrent execution by marking your object as single use (singleton). This has scalability consequences. Every call to the object creates a new thread and a new object, which decreases performance and increases memory usage. At this point, you should consider rewriting your component.


STATUS

This behavior is by design.


MORE INFORMATION

Steps to Reproduce Behavior

  1. Use Performance Monitor (PerfMon) to monitor the following counters:


  2. If you are using one computer as your client, make sure that you have the following options set in Internet Explorer (On the View menu, click Internet Options and then click the Advanced tab:


  3. Create a Visual Basic ActiveX EXE called ThreadWaitProject.ThreadTest, and implement the following function:
    
    Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    
    Function ThreadWait(nSeconds As Long) As Long
        Sleep nSeconds * 1000
        ThreadWait = GetCurrentThreadId
    End Function 


  4. Create an ASP page called threadwait_vb_exe.asp with the following script:
    
    <%
    Option Explicit
    DIM NSec
    
    Sub TestEXE
    response.write "<H1>OOP VB EXE Threadwait</H1>"
    Dim objTest
    Set objTest = Server.CreateObject("ThreadWaitProjectEXE.ThreadSleep")
    Response.Write "StartTime: " & Now & "<BR>"
    Response.Write "ThreadID: " & objTest.ThreadWait(10) & "<BR>"
    Response.Write "EndTime: " & Now & "<BR>"
    Response.write "Session ID: " & Session.SessionId & "<BR>"
    Set objTest = Nothing
    End Sub
    
    TestEXE
    %> 


  5. From two distinct (see the previous step 2) clients, request the Active Server Pages (ASP) page threadwait_vb_exe at the same time.


RESULT: Both requests share the same ThreadID, and the start and end times of both requests are serialized (the second request starts only when the first request has finished). Use PerfMon (step 1) to see that one request is queued while the other is being executed.

Additional query words:


Keywords          : kbASP kbCOMt kbVBp500 kbVBp600 kbGrpASP 
Version           : WINDOWS:5.0,6.0; winnt:4.0
Platform          : WINDOWS winnt 
Issue type        : kbprb 

Last Reviewed: April 6, 1999