2012-07-09 17 views
8

Necesito pasar una devolución de llamada administrada a un receptor TCP no administrado. Como es un hilo que debe existir durante el tiempo de vida de la aplicación, debo evitar que se recolecte la basura. He leído en todas partes que no se requieren punteros de función de fijación y el GCHandle.Alloc hará el trabajo de prevenir la recolección de basura.Pin un puntero a la función

¿Pero esto es un hecho? He visto que la AppPool que aloja este código se bloquea con una infracción de acceso. ¿Por qué no debería sospechar que este error ocurre porque el puntero a la función fue basura?

Esto post es compatible con este hecho.

Actualización: Esto parece haber reducido los bloqueos considerablemente. ¿Hay algún problema con este enfoque?

typedef void (__cdecl *ProcMessageFunc)(void* param, void* paramBuf, ULONG bufSize); 
FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler); 
pin_ptr<MessageFuncDelegate^> pinnedFunctionPointer = &fp; 
ret = Receiver ((ProcMessageFunc)pinnedFunctionPointer); 
+3

Almacenar el objeto delegado en una variable estática es suficiente. El código nativo puede bombardear con violaciones de acceso por muchos otros motivos. –

+0

He hecho exactamente eso. La razón por la que estoy tendiendo a sospechar que la recolección de basura es la causa es porque la violación de acceso ocurre de forma errática. Y, lo que es más importante, la pila de llamadas en el volcado de bloqueo puedo ver el dll nativo seguido de clr.dll y luego kernel32.dll en la parte superior de la pila. Esta orden es consistente. – Krishter

Respuesta

8

que hacer exactamente lo que usted sugiere hacer - GCHandle.Alloc en el delegado, pero sin colocación de clavos - y no he tenido ningún problema en amplio uso en muchas plataformas diferentes y en versiones de .NET 2.0 - 4. Algo como:

DelegateHandle = GCHandle.Alloc(xlDelegate); 
FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate); 

con FunctionPointer después se pasan al código nativo, y DelegateHandle mantuvieron para la limpieza posterior.

Esta parece ser la mejor referencia: http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.80).aspx.

Nada en la entrada que apunta a contradice esta referencia - sí es necesario para proteger el delegado de la recolección de basura, es sólo que colocación de clavos no se requiere.

+0

¿La asignación de direcciones para funciones no es necesaria porque a diferencia de los objetos de montón, existen en una ubicación constante? ¿Qué dirección tiene una función si aún no ha sido JIT por cierto? – Dai

+2

Creo que la llamada a GetFunctionPointerForDelegate crea un pequeño trozo de referencia que tiene un punto de entrada fijo, pero si se mueve el delegado, el talón aún sabrá cómo llamarlo. Por lo tanto, el puntero de función exportado no es una exportación directa de la dirección del objeto delegado (a diferencia de lo que sería una matriz anclada o un miembro de estructura). Recuerde que la función 'nativa' exportada también debe implementar la transición nativa -> administrada. – Govert

+0

Esto es exactamente lo que hice. Lamentablemente, la violación de acceso aún ocurre. Déjame ponerlo de esta manera. ¿Cómo puedo estar completamente seguro de que esta NO es la causa de la violación de acceso? – Krishter

Cuestiones relacionadas