Hi Gil,
OK, I'll try and explain but I am not an expert in this area.
Some GUI functions need to be called from a particular thread, for example in the thread that the parent panel was created in as you have discovered with LoadPanelEx(). This will be to do with variables stored on the stack local to the particular thread and not accessible by other threads.
Now, CVI may implement this slightly differently to the way I describe here, but it will be basically the same result. When you queue an asynchronous procedure call (APC) under Windows, you tell the Windows Thread Scheduler that when it next runs the thread you have posted the APC to, you want it to execute the APC first, before resuming the thread at the point it left off. This means you can have a particular thread do something at the request of a secondary thread next time it runs, which is what you want to do in your case. I think CVI handles things slightly differently because the PostDeferredProcedureCall() help says the posted function runs the next time RunUserInterface() executes, rather than as soon as the thread that RunUserInterface() is in executes. Any NI engineers may be able to explain what the subtle difference might be.
So, what you are doing in your code is getting your secondary thread to tell your main thread to load a child panel to the main panel, which it can do because it is in the correct context, i.e. it can access the correct variable stack. There are other cases where this is useful. For example, if you want to display a popup, and you want that popup to block user access to the GUI until the popup is closed, you must create it in the main GUI thread. It can be displayed from a secondary thread, but if the user clicks another panel, the popup can get hidden, which is rarely what you would want.
Hope this is of some help.
Regards
Jamie Fraser