Q300850: BUG: GlobalMultiUse Class Doesn’t End in Multithreaded Environmt
Article: Q300850
Product(s): Microsoft Visual Basic for Windows
Version(s): 6.0,6.0 SP4,6.0 SP5
Operating System(s):
Keyword(s): kbActiveX kbCOMt kbLocalSvr kbGrpDSVB kbDSupport kbVS600sp4bug
Last Modified: 16-MAY-2002
-------------------------------------------------------------------------------
The information in this article applies to:
- Microsoft Visual Studio versions 6.0 SP4, 6.0 SP5
- Microsoft Visual Basic Enterprise Edition for Windows, versions 6.0 SP4, 6.0 SP5
- Microsoft Visual Basic Professional Edition for Windows, version 6.0
-------------------------------------------------------------------------------
SYMPTOMS
========
When two clients call a procedure of an ActiveX EXE component at the same time,
and this procedure calls another procedure of a MultiUse class in an ActiveX
dynamic-link library (DLL), if this class accesses a procedure in a
GlobalMultiUse class in another ActiveX DLL, the ActiveX EXE component stays in
memory; that is, the process fails to terminate, even after all the references
to it have been released.
This behavior does not occur in Visual Basic 6.0 Service Pack 3 (SP3) or earlier.
CAUSE
=====
This problem occurs because the DllCanUnloadNow function of the GlobalMultiUse
DLL returns FALSE if it is currently being called by another thread. This means
that the GlobalMultiUse DLL may not be able to release itself in a multithreaded
environment.
RESOLUTION
==========
A supported fix that corrects this problem is now available from Microsoft, but
it has not been fully regression tested and should be applied only to computers
that are experiencing this specific problem.
NOTE: You must have a Visual Studio license agreement to obtain this fix.
To resolve this problem, contact Microsoft Product Support Services to obtain the
fix. For a complete list of Microsoft Product Support Services phone numbers and
information on support costs, please go to the following address on the World
Wide Web:
http://support.microsoft.com/default.aspx?scid=fh;EN-US;CNTACTMS
The English version of this fix should have the following file attributes or
later:
Date Time Version Size File name
---------------------------------------------------------
29 May 2001 3:32:23 PM 6.0.92.37 1.32 MB MSVBVM60.DLL
STATUS
======
Microsoft has confirmed this to be a bug in the Microsoft products listed at the
beginning of this article.
MORE INFORMATION
================
Steps to Reproduce Behavior
---------------------------
Create the DLL with a GlobalMultiUse Class:
1. Create a new ActiveX DLL project with a default class, Class1.
2. From the Project menu, click Project1 Properties. Change the project name to
"GMultiUseDll" (without the quotation marks), and then click OK.
3. In the Properties dialog box, set the Instancing property of Class1 to "6 -
GlobalMultiUse".
4. Copy and paste the following code to Class1's code module:
Public Function ClassName() As String
ClassName = "Class1"
End Function
5. From the File menu, click Make GMultiUseDll.dll to compile the project.
GMultiUseDll.dll is created.
Create the DLL with a MultiUse Class:
1. Create a new ActiveX DLL project with a default class, Class1.
2. From the Project menu, click Project1 Properties. Change the project name to
"MultiUseDll" (without the quotation marks), and then click OK.
3. From the Project menu, click References, select the GMultiUseDll.dll check
box, and then click OK.
4. Copy and paste the following code to Class1's code module:
Public Function GetString() As String
GetString = ClassName
End Function
5. From the File menu, click Make MultiUseDll.dll to compile the project.
MultiUseDll.dll is created.
Create the ActiveX EXE Project:
1. Create a new ActiveX EXE project with a default class, Class1.
2. From the Project menu, click Project1 Properties. Change the project name to
"TestServer" (without the quotation marks), and then click OK.
3. From the Project menu, click References, select the MultiUseDll.dll check
box, and then click OK.
4. From the Project menu, click TestServer Properties. On the General tab, set
the Thread Pool to 10 threads.
5. Copy and paste the following code to Class1's code module
Public Sub DoSomething()
Dim obj As MultiuseDll.Class1
Set obj = New MultiuseDll.Class1
obj.GetString
End Sub
6. From the File menu, click Make TextServer.exe to compile the project.
TextServer.exe is created.
Create the Client Project:
1. Create a new Standard EXE project with a default form, Form1.
2. From the Project menu, click Project1 Properties. Change the project name to
"TestClient" (without the quotation marks), and then click OK.
3. Add a Label (Label1), a TextBox (Text1) and two CommandButtons (Command1 and
Command2) to Form1.
4. Copy and paste the following code to Form1's code module:
Dim bStop As Boolean
Private Sub Command1_Click()
Dim oServer As Object
Set oServer = CreateObject("TestServer.Class1")
WaitTRUEinFile Text1.Text
oServer.DoSomething
Set oServer = Nothing
Label1.Caption = "The reference was released"
End Sub
' The purpose of this function is to synchronize the call to the
' GlobalMultiUse DLL through the file Sync.txt.
Private Sub WaitTRUEinFile(sFile As String)
Dim sFlag As String
Label1.Caption = "Waiting for 'TRUE' in " & sFile
Do While bStop = False
Open sFile For Input As #1
Line Input #1, sFlag
Close #1
If UCase(Trim(sFlag)) = "TRUE" Then
Exit Do
End If
DoEvents
Loop
End Sub
Private Sub Command2_Click()
bStop = True
End Sub
Private Sub Form_Load()
Text1.Text = "c:\sync.txt"
Command1.Caption = "Start"
Command2.Caption = "Stop"
bStop = False
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
bStop = True
End Sub
5. From the File menu, click Make TestClient.exe to compile the project.
TestClient.exe is created.
Run the Test:
1. Open Notepad. Add the letter "t" to the first position, and save the file as
Sync.txt in the root of drive C.
2. Start two instances of TestClient.exe. Notice that two TestClient.exe
processes are running in Task Manager.
3. Click Start for both instances of TestClient.
4. Open Sync.txt. Change the first line to "true," and save.
After you save the file, notice the TestServer.exe process in Task Manager.
5. Click Stop for both instances of TestClient, and close the forms. Notice that
there are no instances of TestClient.exe running. At this point,
TestServer.exe stays loaded.
For additional information on issues related to multithreading in Visual Basic,
click the article number below to view the article in the Microsoft Knowledge
Base:
Q241896 PRB: Threading Issues with Visual Basic 6.0 ActiveX Components
Additional query words: multi-thread
======================================================================
Keywords : kbActiveX kbCOMt kbLocalSvr kbGrpDSVB kbDSupport kbVS600sp4bug
Technology : kbVSsearch kbVBSearch kbAudDeveloper kbZNotKeyword6 kbZNotKeyword2 kbVB600Search kbVB600 kbVS600SP4 kbVS600SP5 kbVB600SP4 kbVB600SP5 kbVS600Search
Version : :6.0,6.0 SP4,6.0 SP5
Hardware : ALPHA x86
Issue type : kbbug
Solution Type : kbpending
=============================================================================
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.