سؤال

من الممكن الحصول على تتبع المكدس باستخدام System.Diagnostics.StackTrace، ولكن يجب تعليق مؤشر الترابط.لقد أصبحت وظيفة التعليق والاستئناف قديمة، لذلك أتوقع وجود طريقة أفضل.

هل كانت مفيدة؟

المحلول

ووفقا ل C # 3.0 في باختصار، هذا هو واحد من عدد قليل من الحالات التي كان على ما يرام للاتصال تعليق / استئناف.

نصائح أخرى

إليك ما عملت بالنسبة لي حتى الآن:

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;
}

إذا كان المآزق، وحررت الجمود تلقائيا ونعود أثر فارغة. (يمكنك بعد ذلك يطلق عليه مرة أخرى.)

وأود أن أضيف أنه بعد أيام قليلة من الاختبار، ولقد كنت مرة واحدة فقط قادرة على خلق الجمود على آلة كور i7. المآزق شائعة، على الرغم من يوم واحد الأساسية VM عند تشغيل وحدة المعالجة المركزية بنسبة 100٪.

وهذا هو الموضوع القديم، ولكن أردت فقط أن تحذير حول الحل المقترح: الحل المرحلي واستئناف لا تعمل - لقد واجهت مجرد الجمود في قانون بلدي محاولة تسلسل تعليق / تتبع مكدس الذاكرة المؤقتة / استئناف

والمشكلة هي أن تتبع مكدس الذاكرة المؤقتة منشئ لا RuntimeMethodHandle -> MethodBase التحويلات، وهذا يغير MethodInfoCache الداخلية، والتي تأخذ القفل. حدث الجمود لأن موضوع أنا تدرس أيضا كان يقوم به التفكير، وكان عقد هذا القفل.

ومن المؤسف أن تعليق / لا يتم استئناف الاشياء داخل منشئ تتبع مكدس الذاكرة المؤقتة -then يمكن بسهولة أن تم التحايل على هذه المشكلة.

وكما ذكر في تعليقي، والحل المقترح لا يزال لديهم احتمال صغير لطريق مسدود. تجدون نسختي أدناه.

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();
    }
}
}

وأعتقد، وManualResetEventSlim "fallbackThreadReady" ليس من الضروري حقا، ولكن لماذا يخاطر أي شيء في هذه الحالة الحساسة؟

أعتقد أنك إذا كنت تريد القيام بذلك دون تعاون مؤشر الترابط المستهدف (على سبيل المثال من خلال استدعاء طريقة تحظره على إشارة أو أي شيء أثناء قيام مؤشر الترابط الخاص بك بتتبع المكدس) فستحتاج إلى استخدام واجهات برمجة التطبيقات المهملة.

البديل المحتمل هو استخدام ICorebug القائم على COM الواجهة التي يستخدمها مصححو أخطاء .NET.قد تمنحك قاعدة تعليمات MDbg بداية:

ويبدو أن هذا كان عملية معتمدة في الماضي، ولكن للأسف، قدمت مايكروسوفت هذه عفا عليها الزمن: <لأ href = "https://msdn.microsoft.com/en-us/library/t2k35tat(v=vs. 110) .ASPX "يختلط =" نوفولو noreferrer "> https://msdn.microsoft.com/en-us/library/t2k35tat (ت = vs.110) .aspx اتصال

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top