For one of my contracts I'm implementing a .NET layer over a native third-party SDK.  The SDK makes heavy use of function pointers, which means, in terms of p/invoke and interoperability, I've got a lot of delegates flying around.  I recently hit a rather nasty bug in my .NET layer - see if you can figure this one out.

Consider this truncated example derived from the SDK:

typedef void (__stdcall *PCALLBACK)( HANDLE deviceHandle, LONG32 deviceID );
// ...
API_CALL RESULT_TYPE __stdcall Open( HANDLE deviceHandle, PCALLBACK pfnCallback );

In a nutshell, when Open is called, the pfnCallback function pointer is registered, along with the handle.  The Open function returns almost immediately, and the native library invokes the callback function periodically in response to user interaction with a device.

Here is the C# that enables the Open method to be called from .NET:

public delegate void Callback( IntPtr deviceHandle, int deviceID );
// ...
[DllImport( "ExternalLibrary.dll")]
public static extern ResultCode Open( IntPtr deviceHandle, Callback callback );

And here it is in use:

Result Code result = ExternalLibraryAPI.Open(
    deviceHande,
    delegate( IntPtr handle, int deviceId )
    {
        // ...
    }
);
VerifyResult( result ); 

The call to Open succeeds, and the callback is invoked whenever the user pushes the appropriate button on the device.  Eventually though, a nasty exception is raised as the user continues to fiddle with the device. 

I will tell you that:

  • there is no context or stack information to the exception;
  • there is not a bug in the third-party SDK;
  • this post has all the information you need to find and fix the problem - i.e., I'm not hiding something from you.

So my questions to you are:

  1. What's the exception?
  2. How do you avoid it?
Leave your answers as comments. I'll post the answer in a few days.