public static void Debug(string tag, string format, PObject context, params object[] ps)
        {
            string msg = Format(format, ps);

            if (Thread.CurrentThread.ManagedThreadId == MainThreadID)
            {
                DebugImpl?.Invoke(tag, msg, context);
            }
            else
            {
                lock (DebugThreadQueue)
                {
                    DebugThreadQueue.Enqueue(LogP.Make(tag, msg, context));
                }
            }
        }
        public static void Update()
        {
            while (DebugThreadQueue.Count > 0)
            {
                lock (DebugThreadQueue)
                {
                    var log = DebugThreadQueue.Dequeue();
                    DebugImpl?.Invoke(log.tag, log.msg, log.context);
                }
                return;
            }

            while (WarnThreadQueue.Count > 0)
            {
                lock (WarnThreadQueue)
                {
                    var log = WarnThreadQueue.Dequeue();
                    WarnImpl?.Invoke(log.tag, log.msg, log.context);
                }
                return;
            }

            while (ErrorThreadQueue.Count > 0)
            {
                lock (ErrorThreadQueue)
                {
                    var log = ErrorThreadQueue.Dequeue();
                    ErrorImpl?.Invoke(log.tag, log.msg, log.context);
                }
                return;
            }

            while (AssertThreadQueue.Count > 0)
            {
                lock (AssertThreadQueue)
                {
                    var log = AssertThreadQueue.Dequeue();
                    AssertImpl?.Invoke(log.tag, log.msg, log.context);
                }
                return;
            }

            while (ExpThreadQueue.Count > 0)
            {
                lock (ExpThreadQueue)
                {
                    var log = ExpThreadQueue.Dequeue();
                    ExpImpl?.Invoke(log.tag, log.msg, log.exception, log.context);
                }
                return;
            }

            while (InfoThreadQueue.Count > 0)
            {
                lock (InfoThreadQueue)
                {
                    var log = InfoThreadQueue.Dequeue();
                    InfoImpl?.Invoke(log.tag, log.msg);
                }
                return;
            }

            while (VerboseThreadQueue.Count > 0)
            {
                lock (VerboseThreadQueue)
                {
                    var log = VerboseThreadQueue.Dequeue();
                    VerboseImpl?.Invoke(log.tag, log.msg);
                }
                return;
            }

            while (WtfThreadQueue.Count > 0)
            {
                lock (WtfThreadQueue)
                {
                    var log = WtfThreadQueue.Dequeue();
                    WtfImpl?.Invoke(log.tag, log.msg);
                }
                return;
            }

            while (FatalThreadQueue.Count > 0)
            {
                lock (FatalThreadQueue)
                {
                    var log = FatalThreadQueue.Dequeue();
                    FatalImpl?.Invoke(log.tag, log.msg);
                }
                return;
            }

            while (WriteLineThreadQueue.Count > 0)
            {
                lock (WriteLineThreadQueue)
                {
                    var log = WriteLineThreadQueue.Dequeue();
                    WriteLineImpl?.Invoke(log.lv, log.tag, log.msg);
                }
                return;
            }

            while (ToastShortThreadQueue.Count > 0)
            {
                lock (DebugThreadQueue)
                {
                    var log = ToastShortThreadQueue.Dequeue();
                    ToastShortImpl?.Invoke(log.ptr, log.msg);
                }
                return;
            }

            while (ToastLongThreadQueue.Count > 0)
            {
                lock (ToastLongThreadQueue)
                {
                    var log = ToastLongThreadQueue.Dequeue();
                    ToastLongImpl?.Invoke(log.ptr, log.msg);
                }
            }
        }