В вашем коде, когда вы делаете
callBack setCallBack = new callBack(call);
rv = canusb_setReceiveCallBack(handle, call);
делегат будет доступен для сборки мусора после того, как вы вызовете 'canusb_setReceiveCallBack', потому что в вашем коде нет ни одного делегата, на который есть ссылка.
Вы можете избежать хранения этого в приватном поле.
E.x:.
Class Form1
{
callBack _setCallBack;
private void buttonCallBack_Click(object sender, EventArgs e)
{
_setCallBack = new callBack(call);
rv = canusb_setReceiveCallBack(handle, _setCallBack);
}
}
Но это может иметь некоторые проблемы, потому что каждое нажатие кнопки создает новый обратный вызов. Это может быть проблематично, если необходимо сослаться на предыдущий обратный вызов.
Я думаю, что вы должны сделать рефакторинг кода, чтобы использовать SafeHandle для хранения дескриптора, возвращенного canusb_Open.
Я бы спроектировал класс следующим образом.
class CanUsbSafeHandle : SafeHandle
{
private EventHandler _receiveCallBack;
private readonly object _receiveCallBackLock = new object();
public event EventHandler ReceiveCallBack
{
add
{
lock (_receiveCallBackLock)
{
bool hasListeners = (_receiveCallBack != null);
_receiveCallBack += value;
//call canusb_setReceiveCallBack only when 1 or more listeners were added
//and there were previously no listeners
if (!hasListeners && (_receiveCallBack != null))
{
canusb_setReceiveCallBack(this, setCallBack);
}
}
}
remove
{
lock (_receiveCallBackLock)
{
bool hasListeners = (_receiveCallBack != null);
_receiveCallBack -= value;
//call canusb_setReceiveCallBack only when there are no more listeners.
if(hasListeners && (_receiveCallBack == null))
{
canusb_setReceiveCallBack(this, null);
}
}
}
}
public CanUsbSafeHandle()
: base(IntPtr.Zero, true)
{
}
public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}
protected override bool ReleaseHandle()
{
return canusb_Close(handle);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
lock (_receiveCallBackLock)
{
_receiveCallBack = null;
}
}
base.Dispose(disposing);
}
}
Таким образом, SafeHandle будет управлять временем жизни делегата 'callback' и будет управляться SafeHandle.