- Home /
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.
This is not a blog where you can post your progress over time. You should ask a proper question. It's quite clear that you / your external API does not properly ter$$anonymous$$ate that background thread, When entering / exit playmode any threads you've started will continue to run. You have to properly ter$$anonymous$$ate them.
As the question is currently written it can't be answered in any more detail because it mainly depends on that native code plugin you're using.
Also note when you want to actually update your question you should edit your question and not posting answers. Answers should answer the question. I've converted your answers into comments. However if you want to improve your question or add information that is relevant to the question you should add it to the question itself.
@Bunny83 Clearly the UI on this page is ambiguous. It said "Add your reply", not "Add your answer" or anything like that. Reply can definitely be something other than an answer. If you like to express your feeling please first blame the stuffs who manage this site. At least you don't need to use paragraph 1 AND paragraph 3 to illustrate the same point (I would modify your comment for you if I can).
I know well it's a threading issue. I just illustrated the fact that for the same external API, a CB written in a C++ (a separate dll I created) will not cause the problem, however CB function in c# code DID make Unity freeze. $$anonymous$$ay I know why is that?
Answer by MaxGuernseyIII · Oct 31, 2017 at 05:31 AM
@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:
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.
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.
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. ;)
Thanks @$$anonymous$$axGuernseyIII for your explanation. No I don't have control to the external API. This API was implemented in C / C++ and it worked fine in my previous c++ projects without any threading issue.
I was trying to explore any possible ways to get rid of this problem, which I did, i.e. implementing my own callbacks in c++ and build as another dll. If I use the external API with my own dll (for callbacks to be used in another thread), Unity will exit normally (threads exit fine).
The only difference here is the way I implement those CB (in c# or in a separate c++ dll). I am posting this question just to find out any explanations on my discoveries, or any better way to solve the problem, as managing a c++ dll in addition to the c# code is probably not the most elegant way.
Again really appreciate your help!
Your answer
Follow this Question
Related Questions
Can I code a native plugin for iOS in C/C++? 0 Answers
Is there a way to create a C++ Managed DLL for Unity? 0 Answers
return char** from C++ DLL 0 Answers
Performance: C# vs C++ (plugin) 0 Answers
Android Native Plugin (*.SO) 2 Answers