Unity集成C++项目时出现WrongThreadException的原因及解决方法
Let's break down why you're hitting this error and how to fix it—since I've dealt with similar WinRT/Unity integration issues for HoloLens projects before, I know exactly where this comes from.
Background Context
First, let's align on your setup to make sure we're troubleshooting the right thing:
- You built a minimal C++/CX WinRT component (
MyRuntimeClass) in a UWP project - You imported the resulting
.winmdinto a Unity project configured for IL2CPP + UWP - Your Unity script creates and accesses the C++ class in the
Start()method, but gets a cross-thread exception at runtime
Your Code Reference
Original C++ Header (SomeNamespace.h)
namespace SomeNamespace { public ref class MyRuntimeClass sealed { public: MyRuntimeClass(); bool IsClassInitialized(); private: bool _isRuntimeInitialized = false; }; }
C++ Implementation (SomeNamespace.cpp)
using namespace SomeNamespace; MyRuntimeClass::MyRuntimeClass() { _isRuntimeInitialized = true; } bool MyRuntimeClass::IsClassInitialized() { return _isRuntimeInitialized; };
Unity C# Script (RuntimeSampleUnity.cs)
#if ENABLE_WINMD_SUPPORT using SomeNamespace; #endif public class RuntimeSampleUnity : MonoBehaviour { #if ENABLE_WINMD_SUPPORT private MyRuntimeClass _myRuntimeClass; #endif void Start() { #if ENABLE_WINMD_SUPPORT _myRuntimeClass = new MyRuntimeClass(); var isInit = _myRuntimeClass.IsClassInitialized(); Debug.LogFormat("MyRuntimeClass: {0}", isInit); #endif } }
Why the Exception Happens
WinRT (and by extension C++/CX) components have thread affinity by default:
- The default threading model for sealed C++/CX classes is
STA(Single-Threaded Apartment). This means the object can only be accessed from the exact thread it was created on. - Unity's IL2CPP main thread runs in an
MTA(Multi-Threaded Apartment) environment. When you create theMyRuntimeClassinstance in Unity'sStart()method (on the MTA thread), any subsequent access to its methods tries to cross thread contexts, triggering theWrongThreadException.
Fixing the Issue
The simplest and most robust fix for your use case (integrating non-UI C++ logic like OpenCV) is to modify your C++ class to support multi-threaded access:
Step 1: Update the C++ Class Threading Model
Add the Threading attribute to your class definition to allow access from both STA and MTA threads. You'll need to include the necessary WinRT metadata header first:
// Updated header with threading fix #include <winrt/Windows.Foundation.Metadata.h> namespace SomeNamespace { [Windows::Foundation::Metadata::Threading(Windows::Foundation::Metadata::ThreadingModel::Both)] public ref class MyRuntimeClass sealed { public: MyRuntimeClass(); bool IsClassInitialized(); private: bool _isRuntimeInitialized = false; }; }
ThreadingModel::Bothtells the WinRT runtime that your class doesn't require thread affinity, so it can be accessed from any thread without marshaling.- This is safe for pure logic classes (like your OpenCV wrappers)—you only need to stick with STA if your class interacts with UI elements or other STA-bound WinRT components.
Step 2: Verify Unity Project Settings
Double-check these settings to ensure everything is configured correctly:
- Go to
Edit > Project Settings > Player > Windows- Set
Scripting Backendto IL2CPP - Ensure
Target SDKis set to a UWP version compatible with your HoloLens - Confirm
Enable WinMD Supportis checked
- Set
Additional Notes for HoloLens OpenCV Integration
Since you're migrating an OpenCV/HoloLens project, keep these in mind:
- If your C++ code uses heavy computation, consider offloading it to a background thread (but make sure any WinRT objects used there also use
ThreadingModel::Both). - Avoid accessing Unity's API from background threads—use
UnityMainThreadDispatcheror similar patterns if you need to pass results back to Unity's main thread.
内容的提问来源于stack exchange,提问作者user1729210

