Frage

Es ist möglich, stacktrace zu erhalten mit System.Diagnostics.StackTrace, aber Thread zeitweilig entzogen werden. Suspend und Resume-Funktion sind veraltet, so erwarte ich, dass eine bessere Art und Weise vor.

War es hilfreich?

Lösung

Nach C # 3.0 in a Nutshell , dies ist einer der wenigen Situationen, in denen es in Ordnung ist Suspend / Resume zu rufen.

Andere Tipps

Hier ist, was für mich gearbeitet hat bisher:

StackTrace GetStackTrace (Thread targetThread)
{
    StackTrace stackTrace = null;
    var ready = new ManualResetEventSlim();

    new Thread (() =>
    {
        // Backstop to release thread in case of deadlock:
        ready.Set();
        Thread.Sleep (200);
        try { targetThread.Resume(); } catch { }
    }).Start();

    ready.Wait();
    targetThread.Suspend();
    try { stackTrace = new StackTrace (targetThread, true); }
    catch { /* Deadlock */ }
    finally
    {
        try { targetThread.Resume(); }
        catch { stackTrace = null;  /* Deadlock */  }
    }

    return stackTrace;
}

Wenn es Deadlocks wird die Deadlock automatisch freigegeben und Sie eine Null-Spur zurück. (Sie können es dann wieder aufrufen.)

ich, dass nach ein paar Tagen der Prüfung sollte hinzufügen, ich habe nur einmal in der Lage gewesen, ein Deadlock auf meinem Core i7 Maschine zu erstellen. Deadlocks sind häufig, aber auf Single-Core-VM, wenn die CPU auf 100% läuft.

Dies ist ein altes Thema, aber wollte nur über die vorgeschlagene Lösung warnen. Die Suspend und Resume-Lösung funktioniert nicht - ich gerade erlebte einen Deadlock in meinem Code die Sequenz / Stacktrace / Resume Suspend versuchen

Das Problem ist, dass Stacktrace Konstruktor tut Runtime -> Method Konvertierungen, und dies ändert eine interne MethodInfoCache, die eine Sperre nimmt. Der Deadlock trat auf, weil der Faden Ich prüfe auch Reflexion tat, und hielt diese Sperre.

Es ist schade, dass der Suspend / Resume Sachen nicht im Stacktrace Konstruktor getan werden -dann dieses Problem leicht umgangen werden könnte.

Wie in meinem Kommentar erwähnt, ist die vorgeschlagene Lösung hat noch eine kleine Wahrscheinlichkeit für eine Sackgasse. Bitte finden meine Version unten.

private static StackTrace GetStackTrace(Thread targetThread) {
using (ManualResetEvent fallbackThreadReady = new ManualResetEvent(false), exitedSafely = new ManualResetEvent(false)) {
    Thread fallbackThread = new Thread(delegate() {
        fallbackThreadReady.Set();
        while (!exitedSafely.WaitOne(200)) {
            try {
                targetThread.Resume();
            } catch (Exception) {/*Whatever happens, do never stop to resume the target-thread regularly until the main-thread has exited safely.*/}
        }
    });
    fallbackThread.Name = "GetStackFallbackThread";
    try {
        fallbackThread.Start();
        fallbackThreadReady.WaitOne();
        //From here, you have about 200ms to get the stack-trace.
        targetThread.Suspend();
        StackTrace trace = null;
        try {
            trace = new StackTrace(targetThread, true);
        } catch (ThreadStateException) {
            //failed to get stack trace, since the fallback-thread resumed the thread
            //possible reasons:
            //1.) This thread was just too slow (not very likely)
            //2.) The deadlock ocurred and the fallbackThread rescued the situation.
            //In both cases just return null.
        }
        try {
            targetThread.Resume();
        } catch (ThreadStateException) {/*Thread is running again already*/}
        return trace;
    } finally {
        //Just signal the backup-thread to stop.
        exitedSafely.Set();
        //Join the thread to avoid disposing "exited safely" too early. And also make sure that no leftover threads are cluttering iis by accident.
        fallbackThread.Join();
    }
}
}

denke ich, die ManualResetEventSlim „fallbackThreadReady“ nicht wirklich notwendig ist, aber warum etwas in diesem heiklen Fall riskieren?

Ich glaube, dass, wenn Sie diese von der Ziel-Thread ohne die Zusammenarbeit machen wollen (wie durch eine Methode, die Blöcke auf einer Semaphore oder etwas rufen, während der Thread wird der Stacktrace) Sie die verwenden müssen veraltete APIs.

Eine mögliche Alternative ist die Verwendung der COM-basierte ICorDebug Schnittstelle, die die .NET-Debugger verwenden. Die MDbg Code-Basis könnten Sie einen Start:

Es sieht aus wie diese eine unterstützte Operation in der Vergangenheit war, aber leider hat Microsoft diese veraltet: https://msdn.microsoft.com/en-us/library/t2k35tat (v = vs.110) aspx

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top