2010-09-11 67 views
5

我正在使用調用非託管函數指針的代理。這會導致垃圾收集器在使用前收集它,如MSDN上的CallbackOnCollectedDelegate MDA頁面所述:MSDN page for CallbackOnCollectedDelegate MDA將代理定義爲函數指針

解決方案聲明我必須將相應的委託編組爲非託管函數指針。我最初的反射是使用:

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

然而,C#編譯器不會讓我名帥的委託,即使這是MSDN建議的解決方案。此外,MSDN頁面只顯示了拋出問題的一個例子,但不是解決方案之一。

我該如何將我的委託編組爲非託管函數指針或使它不被GCed?

編輯:正如所建議的,我創建了回調的參考。因此,我的代碼從/變爲:

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

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

現在這個工作 - 但只在調試模式。當我切換到釋放時,它在同一點崩潰。這是爲什麼?

編輯2:更完整的代碼片段:

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); 
    } 
} 

回答

9

你沒有正確讀取。你必須這樣做:

...更改您的代碼,以保持一個參考 到該委託在管理方面 的封 非託管函數指針的壽命。

換句話說,只需將對委託實例的引用存儲在類中,並確保類對象存活足夠長時間。如果你真的必須使用靜態。

+0

編輯,請參閱我的新問題。 – Lazlo 2010-09-11 18:23:11

+1

我無法從非常微薄的代碼片斷中看到存儲「調用」的對象將要存在多長時間。 – 2010-09-11 18:43:30

+0

添加了更完整的代碼片段。 – Lazlo 2010-09-11 18:46:27