private static TraceThread GetOrCreateThread() {
            TraceThread thread = _threads;

            if (thread == null) {
                _threads = thread = new TraceThread();
                thread.Frames = new List<TraceBackFrame>();
            }

            return thread;
        }
        private void DispatchTrace(TraceThread thread, Debugging.TraceEventKind kind, object payload, TracebackDelegate traceDispatch, object traceDispatchObject, TraceBackFrame pyFrame) {
            object args = null;

            // Prepare the event
            string traceEvent = String.Empty;
            switch (kind) {
                case Debugging.TraceEventKind.FrameEnter: traceEvent = "call"; break;
                case Debugging.TraceEventKind.TracePoint: traceEvent = "line"; break;
                case Debugging.TraceEventKind.Exception:
                    traceEvent = "exception";
                    object pyException = PythonExceptions.ToPython((Exception)payload);
                    object pyType = ((IPythonObject)pyException).PythonType;
                    args = PythonTuple.MakeTuple(pyType, pyException, null);
                    break;
                case Debugging.TraceEventKind.FrameExit:
                    traceEvent = "return";
                    args = payload;
                    break;
            }

            bool traceDispatchThrew = true;
            PythonContext.TracePipeline.TraceCallback = null;
            thread.InTraceback = true;
            try {
                TracebackDelegate dlg = traceDispatch(pyFrame, traceEvent, args);
                traceDispatchThrew = false;

                pyFrame.Setf_trace(dlg);
            } finally {
                thread.InTraceback = false;
                PythonContext.TracePipeline.TraceCallback = this;

                if (traceDispatchThrew) {
                    // We're matching CPython's behavior here.  If the trace dispatch throws any exceptions
                    // we don't re-enable tracebacks.  We need to leave the trace callback in place though
                    // so that we can pop our frames.
                    _globalTraceObject = _globalTraceDispatch = null;
                    _exceptionThrown = true;
                }
            }
        }