2009-05-17 5 views
1

J'ai une application de service Windows C# qui transmet un pointeur de fonction de rappel à une DLL C++. J'ai défini à la fois le pointeur de fonction du côté C# et le côté C++ du type __stdcall. Tout fonctionne correctement jusqu'à ce que le rappel soit déclenché par la DLL C++ et lève une violation d'accès d'exception non gérée dans 0x04cb0e. Le débogage s'arrête dans le threadex.c sous l'appel endthread dans l'application C#.C# fournissant des rappels C++, Violation d'accès dans _threadex.c dans endthread()

public delegate void NotificationFunc(int notifycode, IntPtr Userdata); 

[DllImport("notice.dll")] 
void INotify(NotificationFunc notefunc,IntPtr Userdata);//ignore the IntPtr Userdata 
. 
. 
. 
NotificationFunc notefunc = new NotificationFunc(Noticallback); 
INotify(notefunc, Intptr.zero); 

//notice.dll triggers this callback thru the delegate passed in 
void Noticallback(int notifycode, IntPtr userdata) 
{ 
Swtich(notifycode) 
{ 
//my actions 
} 
. 
.//Error Exceptions happens here when trying to end the thread/call 
} 

Je sais que je dois gérer le nettoyage de ces ressources de rappel car il s'agit d'un événement d'appel à sens unique. J'ai essayé GC & GCHandle pour l'empêcher d'être GC mais il semble qu'il y ait toujours une fuite ou une erreur de mémoire. Peut-on aider quelqu'un? Merci

+0

Entreposez-vous le rappel dans une variable locale? Le GC est libre de collecter des variables locales dès qu'il atteint un point où le code ne semble plus le référencer, il est donc possible que votre délégué soit collecté plus tôt qu'il ne semble l'être. En outre, pouvez-vous inclure le code du site d'appel C++ afin que nous puissions voir comment il est appelé et quelle est la signature C++? –

Répondre

1

Wikipedia a un article assez décent sur le sujet. Si j'étais vous, j'utiliserais C++/CLI car c'est plus rapide et moins fortement lié. Ce genre de P/Invoke, où vous mettez en page toutes les définitions partout, est tellement sujette aux erreurs. Et si jamais vous changez, ou si la spécification change sur vous, pour vos types de données ou quelque chose comme ça, C++/CLI sera automatiquement mis à jour, mais malheureusement les déclenchements explicites de P/Invoke comme vous avez ici, devront toujours être re câblé

1

Vous devez empêcher le délégué d'être recueilli par le code managé, en utilisant GCHandle.Alloc:

public delegate void NotificationFunc(int notifycode, IntPtr Userdata); 

    [DllImport("notice.dll")] 
    static extern void INotify(NotificationFunc notefunc,IntPtr Userdata); // Note IntPtr as the callback type 


    NotificationFunc notefunc = new NotificationFunc(Noticallback); 

    // Now, allocate a GCHandle to prevent the delegate from being collected 
    GCHandle handle = GCHandle.Alloc(notefunc); 

    INotify(notefunc, Intptr.Zero); 

    // Free the handle when it's no longer needed 
    handle.Free(); 
Questions connexes