using System; using System.Collections.Concurrent; using System.Threading; using UnityEngine; namespace Kill.Video { /// /// 把任意 Action 排到 Unity 主线程执行。 /// 背景:IL2CPP 的自建后台线程 JVM attach 不可靠,AndroidJavaClass/AndroidJNI /// 在这些线程上 FindClass 会偶发返回空,导致"类未找到/偶尔成功偶尔失败"。 /// 用它在主线程上跑所有 JNI 调用即可稳定。 /// public static class MainThreadDispatcher { private static readonly ConcurrentQueue _pending = new ConcurrentQueue(); private static int _mainThreadId = -1; private static bool _ensured; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] private static void Ensure() { if (_ensured) return; _mainThreadId = Thread.CurrentThread.ManagedThreadId; var go = new GameObject("MainThreadDispatcher"); go.hideFlags = HideFlags.HideAndDontSave; UnityEngine.Object.DontDestroyOnLoad(go); go.AddComponent(); _ensured = true; } public static bool IsMainThread => !_ensured || Thread.CurrentThread.ManagedThreadId == _mainThreadId; /// 在主线程执行 action;若调用方已是主线程则直接内联执行。 public static void RunOnMainThread(Action action) { if (action == null) return; if (IsMainThread) { action(); return; } using (var done = new ManualResetEventSlim(false)) { _pending.Enqueue(() => { try { action(); } finally { done.Set(); } }); done.Wait(); } } private class DispatcherBehaviour : MonoBehaviour { private void Update() { while (_pending.TryDequeue(out var a)) { try { a(); } catch (Exception e) { Debug.LogException(e); } } } } } }