C++ Callback in another thread

Hi All,

I am using an unmanaged c++ API as plugin in one of my Unity projects. The API has an interface to setup callback functions, which will be invoked in another thread managed by the API. I implemented the callback in c#, and marshaled the delegate as function pointer which is used in the c++ API function. The code worked as expected, however when I tried to exit Unity the application froze and stopped responding. I can start and stop play mode as many times as I want, but it just hangs when Unity terminates. Also if I build the project as executable the application also freezes at the end.

I tried another c++ callback which is invoked in the Unity main thread, and unity doesn’t freeze when exiting. Also if I write my callback in c++, build as dll in VS, and import the dll as an intermediate plugin, everything works fine too. Looks like marshaling callbacks works (as long as it’s the same thread), and unmanaged c++ dll with multi-thread is fine as well, however Unity is not happy when combining these two…

Do anyone have similar issue like this? If so is there any solution to that? Thanks for the help!

Today I tried to change unity scripting runtime version to .NET 4.6, and things becomes even worse - Unity will hang when I enter play mode the second time.

Today I tried implementing my callbacks in an external c# dll using unsafe code, unfortunately unity still hangs at exit.
Just to keep posting all my discoveries. Hopefully someone will have a nice answer which explains everything.

@Bunny83 is correct. It is obvious to anyone who has worked with threading that the thread never exits. It is also possible that this is happening because your callback runs forever and blocks the thread.

If the C++ plugin is something you control (which it looks like it is), find a way to end the thread. In most systems, there are three options:

  1. Make it exit gracefully by having a way to cause the outermost loop (and any interior, potentially-infinite loops) to exit. A global “I’m done” flag is something a lot of people done.
  2. Kill the thread using the threading API. Different APIs use different signatures/functions to serve this end but (to my knowledge) they all give you a way to do that.
  3. Mark the thread as a background thread. In a lot of the older threading models - even as recent as Java - this is referred to as a daemon thread. Marking the thread as a daemon basically means “hey, threading API, you can kill this thread when there are no more non-daemon threads”.

If you don’t have control over the thread, the underlying API almost assuredly has a way to cause the thread to be terminated. Look for it.

If you don’t control the creation and destruction of the thread, at least indirectly, and the thread is not being properly closed, call tech support and file a bug. :wink: