On .NET 5 (and .NET core 3 and 3.1) when debugging after around 5 seconds the code throws System.ExecutionEngineException which seems like it should never pop up as it is something obsolete as far as I understood from searching.
The same code on .NET Framework >2 (e.g 4.8 or 4.7.2) similarly works for around 5 seconds then throws the following exception:
Managed Debugging Assistant 'CallbackOnCollectedDelegate' : 'A callback was made on a garbage collected delegate of type 'SoundCheck!SoundCheck.CHCNetSDK+VOICEDATACALLBACKV30::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.'
But on .NET Framework 2 it works magically without any issues.
As far as I understand I should somehow make it so that garbage collection stops and does not collect this method. But I am unfamiliar with this. I do not know how I should approach this.
I am using the Hikvision SDK https://www.hikvision.com/en/support/download/sdk/
The code:
Dll import:
public delegate void VOICEDATACALLBACKV30(int lVoiceComHandle, IntPtr pRecvDataBuffer, uint dwBufSize, byte byAudioFlag, System.IntPtr pUser);
[DllImport(@"..\bin\HCNetSDK.dll")]
public static extern int NET_DVR_StartVoiceCom_V30(int lUserID, uint dwVoiceChan, bool bNeedCBNoEncData, VOICEDATACALLBACKV30 fVoiceDataCallBack, IntPtr pUser);
Start button:
private void btnVioceTalk_Click(object sender, EventArgs e)
{
if (m_bTalk == false)
{
CHCNetSDK.VOICEDATACALLBACKV30 VoiceData = new CHCNetSDK.VOICEDATACALLBACKV30(VoiceDataCallBack);
lVoiceComHandle = CHCNetSDK.NET_DVR_StartVoiceCom_V30(m_lUserID, 1, true, VoiceData, IntPtr.Zero);
if (lVoiceComHandle < 0)
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_StartVoiceCom_V30 failed, error code= " + iLastErr;
MessageBox.Show(str);
return;
}
else
{
btnVioceTalk.Text = "Stop Talk";
m_bTalk = true;
}
}
else
{
if (!CHCNetSDK.NET_DVR_StopVoiceCom(lVoiceComHandle))
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_StopVoiceCom failed, error code= " + iLastErr;
MessageBox.Show(str);
return;
}
else
{
btnVioceTalk.Text = "Start Talk";
m_bTalk = false;
}
}
}
Callback function:
public void VoiceDataCallBack(int lVoiceComHandle, IntPtr pRecvDataBuffer, uint dwBufSize, byte byAudioFlag, System.IntPtr pUser)
{
byte[] sString = new byte[dwBufSize];
Marshal.Copy(pRecvDataBuffer, sString, 0, (Int32)dwBufSize);
if (byAudioFlag ==0)
{
string str = "sound1.pcm";
FileStream fs = new FileStream(str, FileMode.Create);
int iLen = (int)dwBufSize;
fs.Write(sString, 0, iLen);
fs.Close();
}
if (byAudioFlag == 1)
{
string str = "sound2.pcm";
FileStream fs = new FileStream(str, FileMode.Create);
int iLen = (int)dwBufSize;
fs.Write(sString, 0, iLen);
fs.Close();
}
}