Numéro d'article: 241896 - Dernière mise à jour: mercredi 13 juin 2007 - Version: 5.1

Problèmes de thread avec les composants ActiveX Visual Basic 6.0

A noterCet article s'applique à un système d'exploitation différent de celui que vous utilisez. Le contenu de l'article qui ne vous concerne peut-être pas est désactivé.

Sommaire

Agrandir tout | Réduire tout

Symptômes

Lorsque vous utilisez des composants ActiveX Visual Basic 6.0 dans un environnement multithread, vous devez avoir connaissance des problèmes suivants susceptibles de se produire :

DLL ActiveX hébergée dans un client multithread

  • Violation d'accès dans MSVBVM60.DLL.
  • Le client se bloque.
Vous pouvez constater ces deux problèmes si un une DLL ActiveX Visual Basic est hébergée dans un environnement multithread, par exemple, IIS, MTS, ou un client multithread, et si l'option Conservé en mémoire n'est pas activée. Pour activer cette option, procédez comme suit :
  1. À partir du menu Projet, sélectionnez Propriétés du projet.
  2. Sous l'onglet Général, assurez-vous que le Modèle de thread est un thread cloisonné, puis sélectionnez les cases à cocher Mode d'exécution autonome et Conservé en mémoire*.
  3. Enregistrez le projet et compilez la DLL.
* Remarque L'option Mode d'exécution autonome n'est pas disponible si le projet contient des éléments d'interface utilisateur, tels que des formulaires ou des contrôles. L'option Conservé en mémoire n'est pas disponible si Mode d'exécution autonome n'est pas sélectionné.

Remarque Avant le Service Pack 3 de Visual Studio 6.0, il était possible d'obtenir un AV pendant l'arrêt de processus alors que l'option Conservé en mémoire était activée. Ce bogue a été corrigé dans le dernier Service Pack de Visual Studio 6.0 (en anglais) :
http://msdn2.microsoft.com/fr-fr/vstudio/aa718364.aspx (http://msdn2.microsoft.com/fr-fr/vstudio/aa718364.aspx)

Si une DLL ActiveX ou le projet UserControl contient des déclarations d'API, vous pouvez rencontrer des blocages pendant l'arrêt du processus/thread ou la création d'objet, même si la case à cocher Mode d'exécution autonome a été activée dans le cas d'une DLL ActiveX. Pour contourner ce problème, vous pouvez utiliser une Bibliothèque de types au lieu d'une instruction Declare dans Visual Basic. Pour plus d'informations sur la façon d'utiliser une Bibliothèque de types, cliquez sur le numéro%2 ci-dessous pour afficher l'article%2 correspondant dans la Base de connaissances Microsoft.
189133  (http://support.microsoft.com/kb/189133/EN-US/ ) COMMENT FAIRE : Rendre la DLL C plus accessible à VB avec une Bibliothèque de types

ActiveX EXE accédé par un client multithread ou par plusieurs clients à un seul thread ou multithread

Erreur d'exécution '7' : mémoire insuffisante et parfois suivie d'une erreur d'opération sur disque.
Erreur d'exécution '430' : la classe ne gère pas Automation ou l'interface attendue.
Erreur d'exécution '424' : objet requis.
Erreur d'exécution '-2147023170 (800706be)' : erreur Automation. Échec de l'appel de procédure distante.
Erreur d'exécution '-2147287010 (8003001e)' : erreur Automation. Il s'agit d'un message « Une erreur disque s'est produite lors d'une opération de lecture. » basé sur ErrLook.
Des processus serveur supplémentaires (ThreadTest.EXE) sont créés même si la propriété Instancing de Class1 est marquée MultiUse.
Les messages d'erreur ci-dessus peuvent s'afficher si vous avez un serveur ActiveX EXE avec un pool de threads supérieur à un (1), et un client multithread ou plusieurs clients à un seul thread ou multithread qui crée et détruit rapidement des objets à l'intérieur du serveur. Pour contourner ce problème, vous pouvez créer une classe vide sur le serveur local et demander au client de conserver une référence à ce dernier comme indiqué dans la section « Plus d'informations » ci-dessous.

Statut

Ce comportement est voulu par la conception même du produit.Dans Visual Studio 6 Service Pack 5, si un projet contient une classe publique dont l'option MTSTransactionMode est définie par une valeur autre que 0, les options Mode d'exécution autonome et Conservé en mémoire sont automatiquement sélectionnées.

Plus d'informations

Procédure pour reproduire le problème

A : Création du serveur

  1. Créez un projet ActiveX EXE et renommez-le ThreadTest.
  2. Dans le menu Projet, sélectionnez Propriétés du projet et sous l'onglet Général, sélectionnez un Pool de threads sur deux (2).
  3. Ajoutez le code suivant au à la classe par défaut (Class1) :
    Private strClassName As String
    Public Property Let ClassName(ByVal vData As String)
       strClassName = vData
    End Property
    Public Property Get ClassName() As String
       ClassName = strClassName 
    End Property
    					
  4. Enregistrez et compilez le projet (ThreadTest.EXE).

B : Création du client et test

  1. Démarrez un projet EXE standard et renommez-le Client.
  2. Ajoutez un bouton de commande et une zone de texte au formulaire par défaut (Form1).
  3. Ajoutez le code suivant dans Form1:
    Private Sub Command1_Click()
       Dim i As Long, j As Long
       Dim o As Object
       j = Val(Text1.Text)
       For i = 1 To j
          DoEvents
          Set o = CreateObject("ThreadTest.Class1")
          o.ClassName = i
          Me.Caption = o.ClassName
          Set o = Nothing
       Next
    End Sub
    Private Sub Form_Load()
       Text1.Text = 1000
       Command1.Caption = "Start"
    End Sub
    					
  4. Compilez le projet (Client.EXE).
  5. Démarrez trois instances ou plus de Client.EXE et cliquez sur le bouton Démarrer dans chaque formulaire. Notez qu'un ou plusieurs des messages ci-dessus s'affichent.

C: Mise en ?uvre de la solution de contournement

  1. Ouvrez le projet ThreadTest.
  2. Ajoutez un autre module de classe (Class2) sans code.
  3. Enregistrez et recompilez le projet (ThreadTest.EXE).
  4. Ouvrez le projet Client.
  5. Remplacez le code de Form1 par le suivant :
    Private p As Object
    Private Sub Command1_Click()
       Dim i As Long, j As Long
       Dim o As Object
       j = Val(Text1.Text)
       For i = 1 To j
          DoEvents
          Set o = CreateObject("ThreadTest.Class1")
          o.ClassName = i
          Me.Caption = o.ClassName
          Set o = Nothing
       Next
    End Sub
    Private Sub Form_Load()
       Text1.Text = 1000
       Command1.Caption = "Start"   
       Set p = CreateObject("ThreadTest.Class2")
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
       Set p = Nothing
    End Sub
    					
  6. Enregistrez et recompilez le projet (Client.EXE).
  7. Exécutez deux instances ou plus de Client.EXE et cliquez sur le bouton Démarrer dans chaque formulaire. Notez qu'aucun message d'erreur ne doit s'afficher.
Lorsqu'un EXE ActiveX avec un pool de threads supérieur à un est accédé par plusieurs clients via DCOM, la solution de contournement décrite au point C de la section « Plus d'informations » ne fonctionne pas. En conséquence, les serveurs EXE ActiveX de Visual Basic 6.0 ne conviennent pas aux serveurs DCOM comportant plusieurs clients qui créent et détruisent rapidement des objets. Si votre application serveur doit gérer ce scénario, nous vous conseillons vivement d'utiliser à la place des DLL ActiveX dans MTS. Lors de la conception de DLL ActiveX à héberger dans MTS, vous devez vous assurer que les cases à cocher Mode d'exécution autonome et Conservé en mémoire sont toutes deux activées. Ces cases à cocher sont accessibles dans le menu Projet, lorsque vous choisissez Propriétés, et sélectionnez l'onglet Général.

N'utilisez pas la propriété GlobalMultiUse Instancing pour une classe lorsque vous projetez d'utiliser le composant ActiveX sous MTS ou COM+. L'interface de l'objet GlobalMultiUse est mise en cache dans une table par thread et n'est pas libérée avant la fin du thread. En conséquence, si un appel entre avec un contexte différent (bien que situé sur le même thread), il échoue avec RPC_E_WRONG_THREAD. Pour utiliser des composants dans MTS et COM+, vous devez concevoir vos classes de telle sorte que les objets soient sans état.

Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Visual Studio 6.0 Service Pack 3
  • Microsoft Visual Studio 6.0 Enterprise Edition
  • Microsoft Visual Basic 6.0 Édition professionnelle
  • Microsoft Visual Basic 6.0 Édition Entreprise
Mots-clés : 
kbprb kbthread kbtophit KB241896
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.