2010-07-22 5 views
1

J'ai une classe C# que j'ai rendue ComVisible afin qu'elle puisse être utilisée dans une DLL C++ non managée. La classe C# est défini comme ceci:Impossible de se débarrasser de l'objet COM C#

public interface IFSFunction 
{ 
    double GetProcessTime(); 
} 

public class Functions : IFSFunction 
{ 
    // Initialization here 

    // Interface function 
    public double GetProcessTime() 
    { 
     // Do stuff - return a value 
    } 
} 

Puis, dans mon C++ DLL Je reçois une référence à la classe C# comme ceci:

IFSFunctionPtr pIFuncs; 
pIFuncs.CreateInstance(__uuidof(Functions)); 
double proctime = pIFuncs->GetProcessTime() 
pIFuncs.Detach()->Release(); 

Cela appelle les fonctions C# très bien, mais il doesn ne semblent pas nettoyer correctement afterwords. Il semble toujours y avoir une référence à ma classe C# qui traîne. Comment puis-je m'assurer que mon objet C# COM est complètement parti?

+1

Comment savez-vous qu'il existe encore une référence? Quel est le symptôme que vous voyez? –

+1

J'ai mis ce commentaire sur une réponse ci-dessous, aussi, mais ici c'est encore: Voici ma configuration globale: Application-> C++ DLL-> C# COM DLL. Mon application a une fonctionnalité qui me permet de déconnecter la DLL C++ afin que je puisse la recompiler sans avoir à fermer l'application. Lorsque je fais cela, je peux recompiler la DLL C++, mais pas la DLL C#. Je reçois le message suivant: "Le processus ne peut pas accéder au fichier '.. \ .. \ CSFunctions.dll' car il est utilisé par un autre processus." Si je ferme mon application, cette erreur disparaît et je peux construire par DLL. –

Répondre

1

Je vais deviner que vous utilisez un outil de débogage qui vous permet de jeter un coup d'œil sur le tas géré. Comme Windbug.exe avec sos.dll. Oui, vous verrez une instance de l'objet de classe Functions après l'appel Release() final. C'est un objet géré qui suit les règles normales de collecte de place. Il ne sera pas collecté tant que le garbage collector ne sera pas exécuté. Ce sera, tant que vous continuez à exécuter le code géré qui alloue de la mémoire.

+0

En fait, je sais qu'il y a encore quelque chose de connecté à cause d'un symptôme différent. Voici la configuration globale: Application-> C++ DLL-> C# COM DLL. Mon application a une fonctionnalité qui me permet de déconnecter la DLL C++ afin que je puisse la recompiler sans avoir à fermer l'application. Mais quand je fais cela, je peux recompiler la DLL C++, mais pas la DLL C#. Je reçois le message suivant: "Le processus ne peut pas accéder au fichier '.. \ .. \ CSFunctions.dll' car il est utilisé par un autre processus." Est-ce juste parce qu'il attend le Garbage Collector? Devrais-je ignorer ce problème? –

+1

C'est normal. Les DLL managées restent verrouillées et chargées jusqu'à ce que l'AppDomain soit déchargé. Une conséquence directe de la compilation JIT. Ce n'est pas pratique à réparer car ce sera la principale AD. Techniquement c'est possible, vous devrez héberger vous-même le CLR et créer l'AD explicitement. Ignorer. –

+0

Merci. Cela ne pose aucun problème dans le comportement de mon programme, je voulais juste m'assurer que je nettoyais les choses le mieux possible. –

0

Est-ce que cela fonctionne pour vous? (Désolé, il est C# plutôt que C++)

try 
{ 
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(pIFuncs); 
} 
catch (System.Exception ex) 
{ 
    // Do nothing 
} 
finally 
{ 
    pIFuncs = null; 
} 

Infos sur Marshal.FinalReleaseComObjecthere.

+0

J'ai essayé d'appeler FinalReleaseComObject (this) dans ma classe C#, mais j'ai toujours reçu une exception qui disait: "le type de l'objet doit être __ComObject". Je ne sais pas comment contourner ça. –

Questions connexes