一、描述問題
當非托管代碼調用托管應用程序的委托的時候,經常會報錯“托管調試助手 "CallbackOnCollectedDelegate" Message=托管調試助手 "CallbackOnCollectedDelegate":“對“OpenCvSharp!OpenCvSharp.CvMouseCallback::Invoke”類型的已垃圾回收委托進行了回調。這可能會導致應用程序崩潰、損壞和數據丟失。向非托管代碼傳遞委托時,托管應用程序必須讓這些委托保持活動狀態,直到確信不會再次調用它們。”
二、原因分析
GC將局部變量和局部變量引用的委托銷毀了,當托管代碼去訪問委托的時候就會報以上錯誤。
三、解決方法
使用成員變量(比如字段)將需要委托執行的方法放到里面,防止GC回收,而不是將需要執行的方法放到局部變量中。
四、示例說明
錯誤代碼:
調用SetMouseCallback設置回調方法,運行會報以上錯誤:
1 private void button15_Click(object sender, EventArgs e) 2 { 3 Mat mat = GetMat(); 4 Cv2.SetMouseCallback("輸入圖像", GetRGBCallbackMethod); 5 }
正確代碼:
使用字段GetRGBCvMouseCallback來訂閱GetRGBCallbackMethod:
private CvMouseCallback GetRGBCvMouseCallback;
GetRGBCvMouseCallback=new CvMouseCallback(GetRGBCallbackMethod);
Cv2.SetMouseCallback("輸入圖像", GetRGBCvMouseCallback);
原因分析:
因為成員變量CvMouseCallback 不會像局部變量一樣,作用域很小,方法執行完就會被GC回收。