「デリゲートをアンマネージ コードに渡すとき、デリゲートは 2 度と呼び出されないことが確実になるまでマネージ アプリケーションによって維持されなければなりません。」エラーが発生する場合の対処法です。
以下のメッセージが表示されます。
英語では以下です。
デリゲートを格納している変数が解放されてしまったため、コールバックがnullになった可能性があります。
以下のコードではエラーが発生します。
public class LowLevelWavePlay
{
public delegate void WaveOutProc(IntPtr hdrvr, WaveOutMessage uMsg, int dwUser,
IntPtr wavhdr, int dwParam2);
public void OpenWaveOutHandle()
{
WaveOutProc m_BufferProc = new WaveOutProc(WaveOutProcCallback);
MMRESULT rc = waveOutOpen(ref WaveOutHandle, WAVE_MAPPER, ref WaveFormatEx,
m_BufferProc, IntPtr.Zero, CALLBACK_FUNCTION);
}
}
デリゲートを格納する変数 m_BufferProc をOpenWaveOutHandle()メソッド内にローカル変数で宣言しています。このため、関数を抜けた後はガベージコレクションによって任意のタイミングで解放されてしまうため、コールバック関数が呼び出される時点での存在が保証されなくなります。
以下の修正をします。
public class LowLevelWavePlay
{
public delegate void WaveOutProc(IntPtr hdrvr, WaveOutMessage uMsg, int dwUser,
IntPtr wavhdr, int dwParam2);
private WaveOutProc m_BufferProc;
public void OpenWaveOutHandle()
{
m_BufferProc = new WaveOutProc(WaveOutProcCallback);
MMRESULT rc = waveOutOpen(ref WaveOutHandle, WAVE_MAPPER, ref WaveFormatEx,
m_BufferProc, IntPtr.Zero, CALLBACK_FUNCTION);
}
}
デリゲートを格納する変数 m_BufferProc をクラスのメンバ変数として宣言します。メンバ変数で宣言すれば、OpenWaveOutHandle()メソッドを抜けてもm_BufferProc 変数の内容は解放されず保持され続けるため、コールバック関数が正しく呼び出されます。