簡體   English   中英

如何在C#中的每個方法調用中添加Trace()?

[英]How can I add a Trace() to every method call in C#?

我很難跟蹤鎖定問題,所以我想記錄每個方法調用的進入和退出。 我以前用C ++完成了這個,而不必為每個方法添加代碼。 這可能與C#有關嗎?

可能你最好的選擇是使用AOP(面向方面​​編程)框架在方法執行之前和之后自動調用跟蹤代碼。 PostSharp是AOP和.NET的流行選擇。

如果您的主要目標是記錄函數入口/出口點以及兩者之間的臨時信息,我使用Disposable日志記錄對象獲得了良好的結果,其中構造函數跟蹤函數入口Dispose()跟蹤出口 這允許調用代碼將每個方法的代碼簡單地包裝在單個using語句中。 還為其間的任意日志提供了方法。 這是一個完整的C#ETW事件跟蹤類以及函數入口/出口包裝器:

using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace MyExample
{
    // This class traces function entry/exit
    // Constructor is used to automatically log function entry.
    // Dispose is used to automatically log function exit.
    // use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing
    public class FnTraceWrap : IDisposable
    {
        string methodName;
        string className;

        private bool _disposed = false;

        public FnTraceWrap()
        {
            StackFrame frame;
            MethodBase method;

            frame = new StackFrame(1);
            method = frame.GetMethod();
            this.methodName = method.Name;
            this.className = method.DeclaringType.Name;

            MyEventSourceClass.Log.TraceEnter(this.className, this.methodName);
        }

        public void TraceMessage(string format, params object[] args)
        {
            string message = String.Format(format, args);
            MyEventSourceClass.Log.TraceMessage(message);
        }

        public void Dispose()
        {
            if (!this._disposed)
            {
                this._disposed = true;
                MyEventSourceClass.Log.TraceExit(this.className, this.methodName);
            }
        }
    }

    [EventSource(Name = "MyEventSource")]
    sealed class MyEventSourceClass : EventSource
    {
        // Global singleton instance
        public static MyEventSourceClass Log = new MyEventSourceClass();

        private MyEventSourceClass()
        {
        }

        [Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
        public void TraceMessage(string message)
        {
            WriteEvent(1, message);
        }

        [Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
        public void TraceCodeLine([CallerFilePath] string filePath = "",
                                  [CallerLineNumber] int line = 0,
                                  [CallerMemberName] string memberName = "", string message = "")
        {
            WriteEvent(2, filePath, line, memberName, message);
        }

        // Function-level entry and exit tracing
        [Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)]
        public void TraceEnter(string className, string methodName)
        {
            WriteEvent(3, className, methodName);
        }

        [Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)]
        public void TraceExit(string className, string methodName)
        {
            WriteEvent(4, className, methodName);
        }
    }
}

使用它的代碼看起來像這樣:

public void DoWork(string foo)
{
    using (FnTraceWrap fnTrace = new FnTraceWrap())
    {
        fnTrace.TraceMessage("Doing work on {0}.", foo);
        /*
        code ...
        */
    }
}

分析器非常適合在開發過程中查看正在運行的代碼,但如果您正在尋找能夠在生產中執行自定義跟蹤的功能,那么,正如Denis G.所提到的, PostSharp是一個完美的工具:您無需全部更改您的代碼,您可以輕松地打開/關閉它。

它也很容易在幾分鍾內完成設置,PostSharp的創建者GaëlFraiteur甚至還有視頻向您展示向現有應用添加跟蹤是多么容易。
您可以在文檔部分找到示例和教程。

使用Red Gate的ANTS Profiler將是您最好的選擇。 沒錯,看看溫莎城堡的 攔截器 這確實假設你通過IoC加載你的類型。

反射是另一種方式,您可以使用System.Reflection.Emit方法將代碼“寫入”內存。 該代碼可以替換您的方法的代碼,並執行它但具有適當的日志記錄。 祝你好運......但更容易使用Aspect#面向方面編程框架。

它可能正在等待鎖定問題,進行內存轉儲和分析各種線程上的調用堆棧。 您可以使用DebugDiagWindows調試工具附帶的adplus腳本(在本例中為掛起模式)。

Tess Ferrandez還有一個很好的實驗系列 ,學習使用.NET內存轉儲來調試各種問題。 我強烈推薦它。

你怎么知道它正在發生? 如果這是一個多線程應用程序,我建議測試條件並在檢測到時在運行時調用System.Diagnostics.Debugger.Break()。 然后,只需打開Threads窗口並逐步調試每個相關線程上的調用堆棧。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM