2010-09-11 14 views
5

Estoy utilizando un delegado que llama a un puntero de función no administrado. Esto hace que el recolector de basura la recopile antes de usarla, tal como se describe en la página CallbackOnCollectedDelegate MDA en MSDN: MSDN page for CallbackOnCollectedDelegate MDA.Definición de un delegado como un puntero a función

La resolución indica que tengo que reunir el delegado apropiado como un puntero de función no administrado. Mi reflejo inicial era utilizar:

[MarshalAs(UnmanagedType.FunctionPtr)] 
public delegate void EntityCallback([MarshalAs(UnmanagedType.SysInt)] IntPtr entity); 

Sin embargo, el compilador de C# no me deja Marshal un delegado, incluso si esta es la solución sugerida por MSDN. Además, la página de MSDN solo muestra un ejemplo del problema que se está lanzando, pero no de la resolución.

¿Cómo podría ordenar mi delegado como un puntero de función no administrado o evitar que se GCed?

EDIT: Como sugerí, creé una referencia de la devolución de llamada. Por lo tanto, mi código cambió de/a:

// From: 
foo.SetCallback(new EntityCallback(bar)); 

// To: 
call = new EntityCallback(bar); // Referenced in class 
foo.SetCallback(call); 

Ahora esto funciona, pero solo en el modo de depuración. Cuando cambio a Release, se bloquea en el mismo punto. ¿Porqué es eso?

EDIT 2: Código más completo fragmento:

public class Test 
{ 
    private EntityCallback Call; 

    private void Bar(System.IntPtr target) 
    { 
     ... 
    } 

    public Entity Foo { get; set; } 

    public Test() 
    { 
     this.Foo = new Body.Sphere() { Visible = false }; // Irrelevant 
     this.Foo.CollisionType = 3; // Irrelevant 

     this.Call = new EntityCallback(this.Bar); 

     this.Foo.SetCallback(this.Call, EntityCallbackType.Collision); 
    } 
} 

Respuesta

9

Usted no leyó correctamente. Debe hacer esto:

... cambiar el código para mantener una referencia a que el delegado en el lado gestionado durante la vida útil de la puntero de función no administrado calculan las referencias.

En otras palabras, simplemente almacene una referencia a la instancia de delegado en su clase y asegúrese de que el objeto de clase sobreviva lo suficiente. Use una estática si realmente tiene que hacerlo.

+0

Editado, vea mi nueva pregunta, por favor. – Lazlo

+1

No puedo decir por el muy escaso fragmento de código cuánto tiempo estará cerca el objeto que almacena "llamada". –

+0

Agregó un fragmento de código más completo. – Lazlo

Cuestiones relacionadas