2009-07-09 7 views
2

Je suis mise à niveau application vb.net qui gère les événements d'un objet COM (peut-être écrit en VB6) du cadre 1.1 à WPF 2,0/3,5Code Unmanaged appelant rappel vb.net

Le code: (noms d'objet simplifié pour la brièveté)

public class MyClass 
    Private WithEvents serviceMonitor As COMOBJECT.ServiceMonitor 

    Public Sub New() 
     serviceMonitor = New COMOBJECT.ServiceMonitor() 
     serviceMonitor.Connect([some ip address]) 
    End Sub 

    Private Sub ServiceMonitor_ServiceConnectionUp(ByVal MonitorId As Integer, ByVal UserArg As Integer) _ 
     Handles serviceMonitor.ServiceConnectionUp 

     Debug.WriteLine("connection up!") 
    End Sub 

    ' other similar handlers omitted 
End Class 

L'application recevra les rappels comme prévu, mais en quelques secondes, je reçois une violation d'accès. Le code de rappel de base est similaire à la version .net 1.1 bien qu'il fonctionne parfaitement. Selon mes recherches sur l'erreur, il est causé par le garbage collector déplacer des choses autour. Comme je ne transmets aucun objet à manipuler à la DLL, je suppose que les rappels sont les problèmes. D'autres personnes ont résolu cela via un délégué avec <UnmanagedFunctionPointer(CallingConvention.Cdecl)> et/ou Marshal.GetFunctionPointerForDelegate.

Malheureusement, tous les exemples que j'ai trouvés sont des cas où la DLL a une sorte de méthode SetCallback (IntPtr). J'utilise WithEvents et le mot-clé Handles. Voici ma tentative (notez que j'ai supprimé le mot-clé poignées pour que je puisse utiliser AddHandler:

<UnmanagedFunctionPointer(CallingConvention.Cdecl)> _ 
    Delegate Sub ServiceMonitor_ServiceConnectionUpDelegate(ByVal MonitorId As Integer, ByVal UserArg As Integer) 

public class MyClass 
    Private WithEvents serviceMonitor As COMOBJECT.ServiceMonitor 

    Public Sub New() 
     serviceMonitor = New COMOBJECT.ServiceMonitor() 
     del = New ServiceMonitor_ServiceConnectionUpDelegate(AddressOf ServiceMonitor_ServiceConnectionUp) 
     AddHandler serviceMonitor.ServiceConnectionUp, del ' <--- Error here 
     serviceMonitor.Connect([some ip address]) 
    End Sub 

    Private Sub ServiceMonitor_ServiceConnectionUp(ByVal MonitorId As Integer, ByVal UserArg As Integer) 

     Debug.WriteLine("connection up!") 
    End Sub 

    ' other similar handlers omitted 
End Class 

L'erreur que je reçois sur la ligne AddHandler est: « Value of type MyClass.ServiceMonitor_ServiceConnectionUpDelegate cannot be converted to COMOBJECT._IServiceMonitorEvents_ServiceConnectionUpEventHandler »

Quand je souris faites passer le dessus gestionnaire de l'événement, il a une signature: subdéléguer _IServiceMonitorEvents_ServiceConnectionUpEventHandler (ByVal MonitorId As Integer, ByVal UserArg As Integer)

les signatures sont identiques, donc je ne suis pas sûr de ce que le problème est

.

Question 1: Comment utiliser un délégué avec AddHandler de cette manière? Question 2: Est-ce que Marshal.GetFunctionPointerForDelegate() doit être impliqué? Il renvoie un IntPtr mais AddHandler veut un délégué.

Merci d'avance.

Répondre

0

Bien que je ne suis pas encore certain à 100% que le problème est résolu, jusqu'à présent je n'ai pas eu de plus des violations d'accès. Fondamentalement, j'ai supprimé le mot clé WithEvents pour empêcher VB d'utiliser sa propre gestion des erreurs COM -> .net et utilisé à la place les méthodes dans la bibliothèque destinée aux clients C++. J'ai utilisé le <UnmanagedFunctionPointer(CallingConvention.Cdecl)> et passé la bibliothèque un Marshal.GetFunctionPointerForDelegate IntPtr. J'ai également gardé une référence à l'IntPtr, même si cela a peut-être été exagéré.

Je suis confus que j'ai dû passer par tout cela puisque les gestionnaires WithEvents fonctionnaient parfaitement dans .net 1.1. Les différences principales étaient que j'ai utilisé un formulaire pour gérer les rappels plutôt qu'une classe. Un problème persistant est le fait que le débogueur reste parfois en cours d'exécution lorsque je ferme le formulaire d'applications. J'espère que c'est juste une bizarrerie de débogueur.

1

Essayez de déclarer votre délégué comme la classe déléguée prévu:

Public Sub New() 
     serviceMonitor = New COMOBJECT.ServiceMonitor() 
     del = New COMOBJECT._IServiceMonitorEvents_ServiceConnectionUpEventHandler(AddressOf ServiceMonitor_ServiceConnectionUp) 
     AddHandler serviceMonitor.ServiceConnectionUp, del 
     serviceMonitor.Connect([some ip address]) 
    End Sub 
+0

Merci pour la réponse. Je peux faire ceci cependant je ne semble pas créer un délégué non managé approprié parce que j'obtiens toujours des accidents. Je travaille sur un correctif possible: J'ai supprimé le mot-clé WithEvents pour empêcher VB de «câbler» les delagates automatiquement.J'ai ensuite utilisé leur documentation C++ pour transmettre manuellement un IntPtr géré au délégué. Je laisse cette version fonctionner pendant 2 jours sans problème mais j'ai beaucoup de code désactivé en ce moment, donc je ne suis pas sûr si je suis encore sorti du bois. Je vais câbler les autres événements dont j'ai besoin et faire un test approprié. – wtjones