操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊


    出現(xiàn)問(wèn)題時(shí),重要的是提供信息來(lái)幫助診斷問(wèn)題。集成開(kāi)發(fā)環(huán)境 (IDE) 或調(diào)試器可以極大地幫助實(shí)現(xiàn)此效果,但它通常僅在開(kāi)發(fā)期間可用。應(yīng)用程序交付后,應(yīng)用程序本身必須收集和記錄診斷信息。為了滿足此要求,.NET 提供了一組工具來(lái)記錄診斷信息、監(jiān)視應(yīng)用程序行為、檢測(cè)運(yùn)行時(shí)錯(cuò)誤以及與調(diào)試工具(如果可用)集成。

    某些診斷工具和 API 是特定于 Windows 的,因?yàn)樗鼈円蕾囉?Windows 操作系統(tǒng)的功能。為了防止特定于平臺(tái)的 API 使 .NET BCL 混亂,Microsoft 已將它們放在可以選擇引用的單獨(dú) NuGet 中。有十幾個(gè)特定于Windows的軟件包,您可以使用 “master”軟件包一次引用所有軟件包。

    本章中的類型主要在 System.Diagnostics 中定義。

    條件編譯

    可以使用有條件地編譯 C# 中的任何代碼部分。預(yù)處理器指令是編譯器的特殊指令,以 # 符號(hào)開(kāi)頭(與其他 C# 構(gòu)造不同,它必須出現(xiàn)在自己的行上)。從邏輯上講,它們?cè)谥骶幾g發(fā)生之前執(zhí)行(盡管在實(shí)踐中,編譯器在詞法解析階段處理它們)。條件編譯的預(yù)處理器指令是 #if、#else、#endif 和 #elif。

    #if 指令指示編譯器忽略一段代碼,除非定義了指定的。可以使用 #define 指令在源代碼中定義符號(hào)(在這種情況下,符號(hào)僅適用于該文件),也可以使用 <DefineConstants> 元素在 文件中定義符號(hào)(在這種情況下,符號(hào)應(yīng)用于整個(gè)程序集):

    #define TESTMODE            // #define directives must be at top of file
                                // Symbol names are uppercase by convention.
    using System;
    
    class Program
    {
      static void Main()
      {
    #if TESTMODE
        Console.WriteLine ("in test mode!");     // OUTPUT: in test mode!
    #endif
      }
    }

    如果我們刪除第一行,程序?qū)⑹褂脧目蓤?zhí)行文件中完全刪除的 Console.WriteLine 語(yǔ)句進(jìn)行編譯,就好像它被注釋掉了一樣。

    #else 語(yǔ)句類似于 C# 的 else 語(yǔ)句,#elif 等效于 #else 后跟 #if 。的 ||、 && 和 !運(yùn)算符執(zhí)行 和 :

    #if TESTMODE && !PLAYMODE      // if TESTMODE and not PLAYMODE
      ...

    但請(qǐng)記住,您不是在構(gòu)建普通的 C# 表達(dá)式,并且您操作的符號(hào)與(靜態(tài)或其他)完全沒(méi)有聯(lián)系。

    可以通過(guò)編輯 文件(或在 Visual Studio 中轉(zhuǎn)到“項(xiàng)目屬性”窗口中的“生成”選項(xiàng)卡)來(lái)定義應(yīng)用于程序集中每個(gè)文件的符號(hào)。下面定義了兩個(gè)常量,測(cè)試模式和播放模式:

    <PropertyGroup>
      <DefineConstants>TESTMODE;PLAYMODE</DefineConstants>
    </PropertyGroup>

    如果在程序集級(jí)別定義了一個(gè)符號(hào),然后想要為特定文件“取消定義”它,則可以使用 #undef 指令執(zhí)行此操作。

    條件編譯與靜態(tài)變量標(biāo)志

    您可以改為使用簡(jiǎn)單的靜態(tài)字段實(shí)現(xiàn)前面的示例:

    static internal bool TestMode=true;
    
    static void Main()
    {
      if (TestMode) Console.WriteLine ("in test mode!");
    }

    這具有允許運(yùn)行時(shí)配置的優(yōu)點(diǎn)。那么,為什么選擇條件編譯呢?原因是條件編譯可以帶你去變量標(biāo)志不能的地方,例如:

    • 有條件地包含屬性
    • 更改聲明的變量類型
    • 在 using 指令中的不同命名空間或類型別名之間切換;例如:
    • using TestType=#if V2 MyCompany.Widgets.GadgetV2; #else MyCompany.Widgets.Gadget; #endif

    您甚至可以在條件編譯指令下執(zhí)行重大重構(gòu),因此您可以立即在新舊版本之間切換,并編寫(xiě)可針對(duì)多個(gè)運(yùn)行時(shí)版本進(jìn)行編譯的庫(kù),利用可用的最新功能。

    條件編譯的另一個(gè)優(yōu)點(diǎn)是調(diào)試代碼可以引用程序集中未包含在部署中的類型。

    條件屬性

    Condition 屬性指示編譯器忽略對(duì)特定類或方法的任何調(diào)用(如果尚未定義指定的符號(hào))。

    若要了解這有何用處,假設(shè)您編寫(xiě)了一個(gè)用于記錄狀態(tài)信息的方法,如下所示:

    static void LogStatus (string msg)
    {
      string logFilePath=...
      System.IO.File.AppendAllText (logFilePath, msg + "\r\n");
    }

    現(xiàn)在假設(shè)您希望僅在定義了 LOGGINGMODE 符號(hào)時(shí)才執(zhí)行此操作。第一個(gè)解決方案是對(duì) LogStatus 的所有調(diào)用都圍繞一個(gè) #if 指令:

    #if LOGGINGMODE
    LogStatus ("Message Headers: " + GetMsgHeaders());
    #endif

    這給出了一個(gè)理想的結(jié)果,但它很乏味。第二種解決方案是將 #if 指令放在 LogStatus 方法中。但是,如果按如下方式調(diào)用 ,這是有問(wèn)題的:

    LogStatus ("Message Headers: " + GetComplexMessageHeaders());

    GetComplexMessageHeaders 將始終被調(diào)用,這可能會(huì)導(dǎo)致性能下降。

    我們可以通過(guò)將條件屬性(在 System.Diagnostics 中定義)附加到 LogStatus 方法,將第一個(gè)解決方案的功能與第二個(gè)解決方案的便利性結(jié)合起來(lái):

    [Conditional ("LOGGINGMODE")]
    static void LogStatus (string msg)
    {
      ...
    }

    這將指示編譯器將對(duì) LogStatus 的調(diào)用視為包裝在 #if LOGGINGMODE 指令中。如果未定義該符號(hào),則在編譯中完全消除對(duì) LogStatus 的任何調(diào)用,包括其參數(shù)計(jì)算表達(dá)式。(因此,將繞過(guò)任何副作用表達(dá)式。即使 LogStatus 和調(diào)用方位于不同的程序集中,這也有效。

    注意

    [條件] 的另一個(gè)好處是,條件性檢查是在編譯調(diào)用時(shí)執(zhí)行的,而不是在編譯時(shí)執(zhí)行的。這是有益的,因?yàn)樗试S您編寫(xiě)包含 LogStatus 等方法的庫(kù),并且只構(gòu)建該庫(kù)的一個(gè)版本。

    Conditional 屬性在運(yùn)行時(shí)被忽略,它純粹是對(duì)編譯器的指令。

    條件屬性的替代項(xiàng)

    如果需要在運(yùn)行時(shí)動(dòng)態(tài)啟用或禁用功能,則 Condition 屬性毫無(wú)用處:相反,必須使用基于變量的方法。這就留下了一個(gè)問(wèn)題,即在調(diào)用條件日志記錄方法時(shí)如何優(yōu)雅地規(guī)避參數(shù)的計(jì)算。函數(shù)式方法可以解決此問(wèn)題:

    using System;
    using System.Linq;
    
    class Program
    {
      public static bool EnableLogging;
    
      static void LogStatus (Func<string> message)
      {
        string logFilePath=...
        if (EnableLogging)
          System.IO.File.AppendAllText (logFilePath, message() + "\r\n");
      }
    }

    lambda 表達(dá)式允許您調(diào)用此方法而不會(huì)造成語(yǔ)法膨脹:

    LogStatus ( ()=> "Message Headers: " + GetComplexMessageHeaders() );

    如果 EnableLogging 為 false,則永遠(yuǎn)不會(huì)計(jì)算 GetComplexMessageHeaders。

    調(diào)試和跟蹤類

    調(diào)試和跟蹤是提供基本日志記錄和斷言功能的靜態(tài)類。這兩個(gè)類非常相似;主要區(qū)別在于它們的預(yù)期用途。Debug 類用于調(diào)試版本;Trace 類適用于調(diào)試和發(fā)布版本。為此:

    All methods of the Debug class are defined with [Conditional("DEBUG")].
    All methods of the Trace class are defined with [Conditional("TRACE")].

    這意味著編譯器將消除對(duì)調(diào)試或跟蹤所做的所有調(diào)用,除非您定義了 DEBUG 或 TRACE 符號(hào)。(Visual Studio 提供了用于在“項(xiàng)目屬性”的“生成”選項(xiàng)卡中定義這些符號(hào)的復(fù)選框,默認(rèn)情況下,新項(xiàng)目啟用 TRACE 符號(hào)。

    Debug 和 Trace 類都提供 Write、WriteLine 和 WriteIf 方法。默認(rèn)情況下,這些消息將消息發(fā)送到調(diào)試器的輸出窗口:

    Debug.Write     ("Data");
    Debug.WriteLine (23 * 34);
    int x=5, y=3;
    Debug.WriteIf   (x > y, "x is greater than y");

    Trace 類還提供了 TraceInformation 、TraceWarning 和 TraceError 等方法。這些方法和 Write 方法之間的行為差異取決于活動(dòng)的 TraceListener(我們?cè)谥袑?duì)此進(jìn)行了介紹)。

    失敗和斷言

    調(diào)試類和跟蹤類都提供 Fail 和斷言方法。Fail 將消息發(fā)送到調(diào)試或跟蹤類的偵聽(tīng)器集合中的每個(gè) TraceListener(請(qǐng)參閱下一節(jié)),默認(rèn)情況下,該集合將消息寫(xiě)入調(diào)試輸出:

    Debug.Fail ("File data.txt does not exist!");

    如果 bool 參數(shù)為 false,則 Assert 只是調(diào)用 Fail,這稱為,并在違反時(shí)指示代碼中的錯(cuò)誤。指定失敗消息是可選的:

    Debug.Assert (File.Exists ("data.txt"), "File data.txt does not exist!");
    var result=...
    Debug.Assert (result !=null);

    寫(xiě)入、失敗和斷言方法也會(huì)重載,以接受除消息之外的字符串類別,這在處理輸出時(shí)很有用。

    斷言的替代方法是在相反條件為真時(shí)引發(fā)異常。這是驗(yàn)證方法參數(shù)時(shí)的常見(jiàn)做法:

    public void ShowMessage (string message)
    {
      if (message==null) throw new ArgumentNullException ("message");
      ...
    }

    此類“斷言”是無(wú)條件編譯的,靈活性較低,因?yàn)槟鸁o(wú)法通過(guò) TraceListener 控制斷言失敗的結(jié)果。從技術(shù)上講,它們不是斷言。斷言是如果違反,則指示當(dāng)前方法代碼中的錯(cuò)誤。基于參數(shù)驗(yàn)證引發(fā)異常表示代碼中存在 bug。

    跟蹤偵聽(tīng)器

    Trace 類具有一個(gè)靜態(tài) Listeners 屬性,該屬性返回 TraceListener 實(shí)例的集合。它們負(fù)責(zé)處理由寫(xiě)入、失敗和跟蹤方法發(fā)出的內(nèi)容。

    默認(rèn)情況下,每個(gè)偵聽(tīng)器集合都包含一個(gè)偵聽(tīng)器 ( 默認(rèn)跟蹤偵聽(tīng)器 )。默認(rèn)偵聽(tīng)器具有兩個(gè)主要功能:

    • 連接到調(diào)試器(如 Visual Studio)時(shí),消息將寫(xiě)入調(diào)試輸出窗口;否則,將忽略消息內(nèi)容。
    • 調(diào)用 Fail 方法(或斷言失敗)時(shí),應(yīng)用程序?qū)ⅰ?/li>

    可以通過(guò)(可選)刪除默認(rèn)偵聽(tīng)器,然后添加一個(gè)或多個(gè)自己的偵聽(tīng)器來(lái)更改此行為。您可以從頭開(kāi)始編寫(xiě)跟蹤偵聽(tīng)器(通過(guò)子類化 TraceListener ),也可以使用預(yù)定義的類型之一:

    • TextWriterTraceListener 寫(xiě)入 Stream 或 TextWriter 或追加到文件。
    • EventLogTraceListener 寫(xiě)入 Windows 事件日志(僅限 Windows)。
    • EventProviderTraceListener 寫(xiě)入 Windows 事件跟蹤 (ETW) 子系統(tǒng)(跨平臺(tái)支持)。

    TextWriterTraceListener 進(jìn)一步子類化為 ConsoleTraceListener、 、XmlWriterTraceListener 和 EventSchemaTraceListener。

    下面的示例清除 Trace 的默認(rèn)偵聽(tīng)器,然后添加三個(gè)偵聽(tīng)器,一個(gè)追加到文件,一個(gè)寫(xiě)入控制臺(tái),另一個(gè)寫(xiě)入 Windows 事件日志:

    // Clear the default listener:
    Trace.Listeners.Clear();
    
    // Add a writer that appends to the trace.txt file:
    Trace.Listeners.Add (new TextWriterTraceListener ("trace.txt"));
    
    // Obtain the Console's output stream, then add that as a listener:
    System.IO.TextWriter tw=Console.Out;
    Trace.Listeners.Add (new TextWriterTraceListener (tw));
    
    // Set up a Windows Event log source and then create/add listener.
    // CreateEventSource requires administrative elevation, so this would
    // typically be done in application setup.
    if (!EventLog.SourceExists ("DemoApp"))
      EventLog.CreateEventSource ("DemoApp", "Application");
    
    Trace.Listeners.Add (new EventLogTraceListener ("DemoApp"));

    對(duì)于 Windows 事件日志,使用 寫(xiě)入 、 失敗 或 斷言 方法編寫(xiě)的消息始終在 Windows 事件查看器中顯示為“信息”消息。但是,通過(guò) TraceWarning 和 TraceError 方法編寫(xiě)的消息將顯示為警告或錯(cuò)誤。

    TraceListener 還具有 TraceFilter 類型的篩選器,您可以設(shè)置該篩選器以控制是否將消息寫(xiě)入該偵聽(tīng)器。為此,您可以實(shí)例化預(yù)定義的子類之一( 事件類型篩選器 或 源篩選器 ),或者子類 TraceFilter 并重寫(xiě) ShouldTrace 方法。例如,您可以使用它按類別進(jìn)行過(guò)濾。

    TraceListener 還定義了用于控制縮進(jìn)的 IndentLevel 和 IndentSize 屬性,以及用于寫(xiě)入額外數(shù)據(jù)的 TraceOutputOptions 屬性:

    TextWriterTraceListener tl=new TextWriterTraceListener (Console.Out);
    tl.TraceOutputOptions=TraceOptions.DateTime | TraceOptions.Callstack;

    使用 Trace 方法時(shí)應(yīng)用跟蹤輸出選項(xiàng):

    Trace.TraceWarning ("Orange alert");
    
    DiagTest.vshost.exe Warning: 0 : Orange alert
         DateTime=2007-03-08T05:57:13.6250000Z
         Callstack=at System.Environment.GetStackTrace(Exception e, Boolean
    needFileInfo)
         at System.Environment.get_StackTrace()     at ...

    刷新和關(guān)閉偵聽(tīng)器

    某些偵聽(tīng)器(如 TextWriterTraceListener)最終會(huì)寫(xiě)入受緩存影響的流。這有兩個(gè)含義:

    • 消息可能不會(huì)立即顯示在輸出流或文件中。
    • 您必須在應(yīng)用程序結(jié)束之前關(guān)閉(或至少刷新)偵聽(tīng)器;否則,您將丟失緩存中的內(nèi)容(默認(rèn)情況下,如果您正在寫(xiě)入文件,則最多為 4 KB)。

    Trace 和 Debug 類提供靜態(tài)的 Close 和 Flush 方法,這些方法在所有偵聽(tīng)器上調(diào)用 Close 或 Flush(而偵聽(tīng)器又在任何基礎(chǔ)器和流上調(diào)用 Close 或 Flush)。Close 隱式調(diào)用 Flush ,關(guān)閉文件句柄,并防止寫(xiě)入進(jìn)一步的數(shù)據(jù)。

    作為一般規(guī)則,在應(yīng)用程序結(jié)束之前調(diào)用 Close,并隨時(shí)調(diào)用 Flush 以確保寫(xiě)入當(dāng)前消息數(shù)據(jù)。這適用于使用基于流或文件的偵聽(tīng)器。

    跟蹤和調(diào)試還提供自動(dòng)刷新屬性,如果為 true,則在每條消息后強(qiáng)制刷新。

    注意

    如果使用任何基于文件或流的偵聽(tīng)器,則最好在“調(diào)試和跟蹤”上將自動(dòng)刷新設(shè)置為 true。否則,如果發(fā)生未經(jīng)處理的異常或嚴(yán)重錯(cuò)誤,最后 4 KB 的診斷信息可能會(huì)丟失。

    調(diào)試器集成

    有時(shí),應(yīng)用程序與調(diào)試器交互(如果可用)很有用。在開(kāi)發(fā)過(guò)程中,調(diào)試器通常是您的IDE(例如,Visual Studio);在部署中,調(diào)試器更可能是較低級(jí)別的調(diào)試工具之一,例如 WinDbg、Cordbg 或 MDbg。

    連接和斷開(kāi)

    System.Diagnostics中的靜態(tài)調(diào)試器類提供了與調(diào)試器交互的基本函數(shù),即中斷、啟動(dòng)、日志和IsAttached 。

    調(diào)試器必須首先附加到應(yīng)用程序才能對(duì)其進(jìn)行調(diào)試。如果從 IDE 中啟動(dòng)應(yīng)用程序,則會(huì)自動(dòng)執(zhí)行此操作,除非您另有請(qǐng)求(通過(guò)選擇“啟動(dòng)但不調(diào)試”)。但是,有時(shí)在 IDE 中以調(diào)試模式啟動(dòng)應(yīng)用程序是不方便或不可能的。一個(gè)例子是Windows Service應(yīng)用程序或(具有諷刺意味的)Visual Studio設(shè)計(jì)器。一種解決方案是正常啟動(dòng)應(yīng)用程序,然后在 IDE 中選擇“調(diào)試進(jìn)程”。但是,這不允許在程序執(zhí)行的早期設(shè)置斷點(diǎn)。

    解決方法是從應(yīng)用程序內(nèi)部調(diào)用 Debugger.Break。此方法啟動(dòng)調(diào)試器,附加到該調(diào)試器,并在該點(diǎn)掛起執(zhí)行。(啟動(dòng)執(zhí)行相同的操作,但不暫停執(zhí)行。附加后,可以使用 Log 方法將消息直接記錄到調(diào)試器的輸出窗口。可以通過(guò)檢查 IsAttached 屬性來(lái)驗(yàn)證是否已附加到調(diào)試器。

    調(diào)試器屬性

    DebuggerStepThrough 和 DebuggerHidden 屬性向調(diào)試器提供有關(guān)如何處理特定方法、構(gòu)造函數(shù)或類的單步執(zhí)行的建議。

    調(diào)試器單步執(zhí)行請(qǐng)求調(diào)試器在沒(méi)有任何用戶交互的情況下單步執(zhí)行函數(shù)。此屬性在自動(dòng)生成的方法和將實(shí)際工作轉(zhuǎn)發(fā)到其他位置的方法的代理方法中很有用。在后一種情況下,如果在“real”方法中設(shè)置了斷點(diǎn),調(diào)試器仍將在調(diào)用堆棧中顯示代理方法,除非還添加了 DebuggerHidden 屬性。可以在代理上組合這兩個(gè)屬性,以幫助用戶專注于調(diào)試應(yīng)用程序邏輯而不是管道:

    [DebuggerStepThrough, DebuggerHidden]
    void DoWorkProxy()
    {
      // setup...
      DoWork();
      // teardown...
    }
    
    void DoWork() {...}   // Real method...

    進(jìn)程和進(jìn)程線程

    我們?cè)诘淖詈笠还?jié)中描述了如何使用 Process.Start 啟動(dòng)一個(gè)新進(jìn)程。Process 類還允許您查詢?cè)谕慌_(tái)或另一臺(tái)計(jì)算機(jī)上運(yùn)行的其他進(jìn)程并與之交互。Process 類是 .NET 標(biāo)準(zhǔn) 2.0 的一部分,盡管其功能僅限于 UWP 平臺(tái)。

    檢查正在運(yùn)行的進(jìn)程

    這些方法按名稱或進(jìn)程 ID 檢索特定進(jìn)程,或檢索當(dāng)前計(jì)算機(jī)或指定計(jì)算機(jī)上運(yùn)行的所有進(jìn)程。這包括托管和非托管進(jìn)程。每個(gè) Process 實(shí)例都有豐富的屬性映射統(tǒng)計(jì)信息,例如名稱、ID、優(yōu)先級(jí)、內(nèi)存和處理器利用率、窗口句柄等。下面的示例枚舉當(dāng)前計(jì)算機(jī)上所有正在運(yùn)行的進(jìn)程:Process.GetProcessXXX

    foreach (Process p in Process.GetProcesses())
    using (p)
    {
      Console.WriteLine (p.ProcessName);
      Console.WriteLine ("   PID:      " + p.Id);
      Console.WriteLine ("   Memory:   " + p.WorkingSet64);
      Console.WriteLine ("   Threads:  " + p.Threads.Count);
    }

    Process.GetCurrentProcess 返回當(dāng)前進(jìn)程。

    可以通過(guò)調(diào)用進(jìn)程的 Kill 方法來(lái)終止進(jìn)程。

    檢查進(jìn)程中的線程

    還可以使用 Process.Threads 屬性枚舉其他進(jìn)程的線程。但是,您獲得的對(duì)象不是 System.Threading.Thread 對(duì)象;它們是 ProcessThread 對(duì)象,用于管理任務(wù)而不是同步任務(wù)。ProcessThread 對(duì)象提供有關(guān)基礎(chǔ)線程的診斷信息,并允許您控制它的某些方面,例如其優(yōu)先級(jí)和處理器關(guān)聯(lián)性:

    public void EnumerateThreads (Process p)
    {
      foreach (ProcessThread pt in p.Threads)
      {
        Console.WriteLine (pt.Id);
        Console.WriteLine ("   State:    " + pt.ThreadState);
        Console.WriteLine ("   Priority: " + pt.PriorityLevel);
        Console.WriteLine ("   Started:  " + pt.StartTime);
        Console.WriteLine ("   CPU time: " + pt.TotalProcessorTime);
      }
    }

    StackTrace 和 StackFrame

    類提供執(zhí)行調(diào)用堆棧的只讀視圖。您可以獲取當(dāng)前線程或異常對(duì)象的堆棧跟蹤。此類信息主要用于診斷目的,盡管您也可以在編程(黑客)中使用它。堆棧跟蹤表示一個(gè)完整的調(diào)用堆棧;StackFrame 表示該堆棧中的單個(gè)方法調(diào)用。

    注意

    如果只需要知道調(diào)用方法的名稱和行號(hào),則調(diào)用方信息屬性可以提供更簡(jiǎn)單、更快捷的替代方法。我們將在第 的中介紹此主題。

    如果實(shí)例化不帶參數(shù)的 StackTrace 對(duì)象(或使用布爾參數(shù)),則會(huì)獲得當(dāng)前線程調(diào)用堆棧的快照。如果為 true,則 bool 參數(shù)指示 StackTrace 讀取程序集(項(xiàng)目調(diào)試)文件(如果存在),從而使您能夠訪問(wèn)文件名、行號(hào)和列偏移量數(shù)據(jù)。使用 /debug 開(kāi)關(guān)進(jìn)行編譯時(shí),將生成項(xiàng)目調(diào)試文件。(Visual Studio 使用此開(kāi)關(guān)進(jìn)行編譯,除非您通過(guò)提出其他請(qǐng)求。

    獲得 StackTrace 后,您可以通過(guò)調(diào)用 GetFrame 來(lái)檢查特定幀,或者使用 GetFrame 獲取整個(gè)幀:

    static void Main() { A (); }
    static void A()    { B (); }
    static void B()    { C (); }
    static void C()
    {
      StackTrace s=new StackTrace (true);
    
      Console.WriteLine ("Total frames:   " + s.FrameCount);
      Console.WriteLine ("Current method: " + s.GetFrame(0).GetMethod().Name);
      Console.WriteLine ("Calling method: " + s.GetFrame(1).GetMethod().Name);
      Console.WriteLine ("Entry method:   " + s.GetFrame
                                           (s.FrameCount-1).GetMethod().Name);
      Console.WriteLine ("Call Stack:");
      foreach (StackFrame f in s.GetFrames())
        Console.WriteLine (
          "  File: "   + f.GetFileName() +
          "  Line: "   + f.GetFileLineNumber() +
          "  Col: "    + f.GetFileColumnNumber() +
          "  Offset: " + f.GetILOffset() +
          "  Method: " + f.GetMethod().Name);
    }

    下面是輸出:

    Total frames:   4
    Current method: C
    Calling method: B
    Entry method: Main
    Call stack:
      File: C:\Test\Program.cs  Line: 15  Col: 4  Offset: 7  Method: C
      File: C:\Test\Program.cs  Line: 12  Col: 22  Offset: 6  Method: B
      File: C:\Test\Program.cs  Line: 11  Col: 22  Offset: 6  Method: A
      File: C:\Test\Program.cs  Line: 10  Col: 25  Offset: 6  Method: Main

    注意

    中間語(yǔ)言 (IL) 偏移量表示將執(zhí)行的指令的偏移量,而不是當(dāng)前正在執(zhí)行的指令的偏移量。但是,奇怪的是,行號(hào)和列號(hào)(如果存在文件)通常指示實(shí)際的執(zhí)行點(diǎn)。

    發(fā)生這種情況是因?yàn)?CLR 在從 IL 偏移量計(jì)算行和列時(shí)會(huì)盡力實(shí)際執(zhí)行點(diǎn)。編譯器以這樣一種方式發(fā)出 IL,包括將 nop(無(wú)操作)指令插入 IL 流中。

    但是,在啟用優(yōu)化的情況下進(jìn)行編譯會(huì)禁用 nop 指令的插入,因此堆棧跟蹤可能會(huì)顯示要執(zhí)行的下一條語(yǔ)句的行號(hào)和列號(hào)。由于優(yōu)化可能會(huì)拉出其他技巧(包括折疊整個(gè)方法),因此進(jìn)一步阻礙了獲取有用的堆棧跟蹤。

    獲取整個(gè) StackTrace 基本信息的快捷方式是在其上調(diào)用 ToString。結(jié)果如下所示:

       at DebugTest.Program.C() in C:\Test\Program.cs:line 16
       at DebugTest.Program.B() in C:\Test\Program.cs:line 12
       at DebugTest.Program.A() in C:\Test\Program.cs:line 11
       at DebugTest.Program.Main() in C:\Test\Program.cs:line 10

    您還可以通過(guò)將異常傳遞到 StackTrace 的中來(lái)獲取異常對(duì)象的堆棧跟蹤(顯示導(dǎo)致引發(fā)異常的原因)。

    注意

    異常已具有 StackTrace 屬性;但是,此屬性返回一個(gè)簡(jiǎn)單的字符串,而不是 StackTrace 對(duì)象。StackTrace 對(duì)象在記錄部署后發(fā)生的異常(沒(méi)有文件)時(shí)要有用得多,因?yàn)槟梢杂涗?量來(lái)代替行號(hào)和列號(hào)。使用 IL 偏移量和 ,您可以查明方法中發(fā)生錯(cuò)誤的位置。

    視窗事件日志

    Win32 平臺(tái)以 Windows 事件日志的形式提供集中式日志記錄機(jī)制。

    我們之前使用的調(diào)試和跟蹤類將寫(xiě)入 Windows 事件日志,如果您注冊(cè)了 EventLogTraceListener 。但是,使用 EventLog 類,可以直接寫(xiě)入 Windows 事件日志,而無(wú)需使用 Trace 或 Debug 。還可以使用此類來(lái)讀取和監(jiān)視事件數(shù)據(jù)。

    注意

    寫(xiě)入 Windows 事件日志在 Windows 服務(wù)應(yīng)用程序中是有意義的,因?yàn)槿绻霈F(xiàn)問(wèn)題,則無(wú)法彈出用戶界面,將用戶定向到已寫(xiě)入診斷信息的某些特殊文件。此外,由于服務(wù)寫(xiě)入 Windows 事件日志是常見(jiàn)的做法,因此,如果服務(wù)失敗,管理員可能會(huì)首先查看此位置。

    有三個(gè)標(biāo)準(zhǔn)的 Windows 事件日志,由以下名稱標(biāo)識(shí):

    • 應(yīng)用
    • 系統(tǒng)
    • 安全

    應(yīng)用程序日志是大多數(shù)應(yīng)用程序通常寫(xiě)入的位置。

    寫(xiě)入事件日志

    寫(xiě)入 Windows 事件日志:

    1. 選擇三個(gè)事件日志(通常是)之一。
    2. 確定并在必要時(shí)創(chuàng)建它(創(chuàng)建需要管理權(quán)限)。
    3. 使用日志名稱、源名稱和消息數(shù)據(jù)調(diào)用 EventLog.WriteEntry。

    是應(yīng)用程序的易于識(shí)別的名稱。必須先注冊(cè)源名稱,然后才能使用它 - CreateEventSource 方法執(zhí)行此功能。然后,您可以調(diào)用 WriteEntry :

    const string SourceName="MyCompany.WidgetServer";
    
    // CreateEventSource requires administrative permissions, so this would
    // typically be done in application setup.
    if (!EventLog.SourceExists (SourceName))
      EventLog.CreateEventSource (SourceName, "Application");
    
    EventLog.WriteEntry (SourceName,
      "Service started; using configuration file=...",
      EventLogEntryType.Information);

    事件日志條目類型可以是 信息 、 警告 、 錯(cuò)誤 、 成功審核 或 失敗審核 。每個(gè)事件在 Windows 事件查看器中都顯示不同的圖標(biāo)。您還可以選擇指定類別和事件 ID(每個(gè)都是您自己選擇的數(shù)字)并提供可選的二進(jìn)制數(shù)據(jù)。

    CreateEventSource 還允許您指定計(jì)算機(jī)名稱:如果您有足夠的權(quán)限,則寫(xiě)入另一臺(tái)計(jì)算機(jī)的事件日志。

    讀取事件日志

    若要讀取事件日志,請(qǐng)使用要訪問(wèn)的日志的名稱和日志所在的另一臺(tái)計(jì)算機(jī)的名稱(可選)實(shí)例化 EventLog 類。然后,可以通過(guò) Entries 集合屬性讀取每個(gè)日志條目:

    EventLog log=new EventLog ("Application");
    
    Console.WriteLine ("Total entries: " + log.Entries.Count);
    
    EventLogEntry last=log.Entries [log.Entries.Count - 1];
    Console.WriteLine ("Index:   " + last.Index);
    Console.WriteLine ("Source:  " + last.Source);
    Console.WriteLine ("Type:    " + last.EntryType);
    Console.WriteLine ("Time:    " + last.TimeWritten);
    Console.WriteLine ("Message: " + last.Message);

    您可以通過(guò)靜態(tài)方法 EventLog.GetEventLogs 枚舉當(dāng)前(或其他)計(jì)算機(jī)的所有日志(這需要管理權(quán)限才能進(jìn)行完全訪問(wèn)):

    foreach (EventLog log in EventLog.GetEventLogs())
      Console.WriteLine (log.LogDisplayName);

    這通常至少打印。

    監(jiān)視事件日志

    每當(dāng)條目寫(xiě)入 Windows 事件日志時(shí),都可以通過(guò) EntryWrite 事件收到警報(bào)。這適用于本地計(jì)算機(jī)上的事件日志,無(wú)論哪個(gè)應(yīng)用程序記錄了事件,它都會(huì)觸發(fā)。

    要啟用日志監(jiān)控:

    1. 實(shí)例化事件日志并將其 EnableRaisingEvents 屬性設(shè)置為 true 。
    2. 處理 EntryWrite 事件。

    例如:

    using (var log=new EventLog ("Application"))
    {
      log.EnableRaisingEvents=true;
      log.EntryWritten +=DisplayEntry;
      Console.ReadLine();
    }
    
    void DisplayEntry (object sender, EntryWrittenEventArgs e)
    {
      EventLogEntry entry=e.Entry;
      Console.WriteLine (entry.Message);
    }

    性能計(jì)數(shù)器

    注意

    性能計(jì)數(shù)器是僅限 Windows 的功能,需要 NuGet 包 System.Diagnostics.PerformanceCounter 。如果您面向 Linux 或 macOS,請(qǐng)參閱了解替代方案。

    到目前為止,我們討論的日志記錄機(jī)制對(duì)于捕獲信息以供將來(lái)分析非常有用。但是,要深入了解應(yīng)用程序(或整個(gè)系統(tǒng))的當(dāng)前狀態(tài),需要一種更實(shí)時(shí)的方法。滿足此需求的 Win32 解決方案是性能監(jiān)視基礎(chǔ)結(jié)構(gòu),它由系統(tǒng)和應(yīng)用程序公開(kāi)的一組性能計(jì)數(shù)器以及用于實(shí)時(shí)監(jiān)視這些計(jì)數(shù)器的Microsoft管理控制臺(tái) (MMC) 管理單元組成。

    性能計(jì)數(shù)器分為“系統(tǒng)”、“處理器”、“.NET CLR 內(nèi)存”等類別。這些類別有時(shí)也被 GUI 工具稱為“性能對(duì)象”。每個(gè)類別對(duì)一組相關(guān)的性能計(jì)數(shù)器進(jìn)行分組,這些性能計(jì)數(shù)器監(jiān)視系統(tǒng)或應(yīng)用程序的一個(gè)方面。“.NET CLR 內(nèi)存”類別中的性能計(jì)數(shù)器示例包括“GC 中的時(shí)間百分比”、“所有堆中的 # 字節(jié)數(shù)”和“分配的字節(jié)/秒”。

    每個(gè)類別可以選擇具有一個(gè)或多個(gè)可以獨(dú)立監(jiān)視的實(shí)例。例如,這在“處理器”類別中的“處理器時(shí)間百分比”性能計(jì)數(shù)器中很有用,它允許監(jiān)視 CPU 利用率。在多處理器計(jì)算機(jī)上,此計(jì)數(shù)器支持每個(gè) CPU 的實(shí)例,允許您獨(dú)立監(jiān)視每個(gè) CPU 的利用率。

    以下各節(jié)演示如何執(zhí)行通常需要的任務(wù),例如確定公開(kāi)的計(jì)數(shù)器、監(jiān)視計(jì)數(shù)器以及創(chuàng)建自己的計(jì)數(shù)器以公開(kāi)應(yīng)用程序狀態(tài)信息。

    注意

    讀取性能計(jì)數(shù)器或類別可能需要本地或目標(biāo)計(jì)算機(jī)上的管理員權(quán)限,具體取決于訪問(wèn)的內(nèi)容。

    枚舉可用計(jì)數(shù)器

    下面的示例枚舉計(jì)算機(jī)上所有可用的性能計(jì)數(shù)器。對(duì)于具有實(shí)例的用戶,它會(huì)枚舉每個(gè)實(shí)例的計(jì)數(shù)器:

    PerformanceCounterCategory[] cats=PerformanceCounterCategory.GetCategories();
    
    foreach (PerformanceCounterCategory cat in cats)
    {
      Console.WriteLine ("Category: " + cat.CategoryName);
    
      string[] instances=cat.GetInstanceNames();
      if (instances.Length==0)
      {
        foreach (PerformanceCounter ctr in cat.GetCounters())
          Console.WriteLine ("  Counter: " + ctr.CounterName);
      }
      else   // Dump counters with instances
      {
        foreach (string instance in instances)
        {
          Console.WriteLine ("  Instance: " + instance);
          if (cat.InstanceExists (instance))
            foreach (PerformanceCounter ctr in cat.GetCounters (instance))
              Console.WriteLine ("    Counter: " + ctr.CounterName);
        }
      }
    }

    注意

    結(jié)果是超過(guò) 10,000 行長(zhǎng)!執(zhí)行也需要一段時(shí)間,因?yàn)?PerformanceCounterCategory.InstanceExists 的實(shí)現(xiàn)效率低下。在實(shí)際系統(tǒng)中,您只希望按需檢索更詳細(xì)的信息。

    下一個(gè)示例使用 LINQ 僅檢索 .NET 性能計(jì)數(shù)器,并將結(jié)果寫(xiě)入 XML 文件:

    var x=new XElement ("counters",
        from PerformanceCounterCategory cat in
             PerformanceCounterCategory.GetCategories()
        where cat.CategoryName.StartsWith (".NET")
        let instances=cat.GetInstanceNames()
        select new XElement ("category",
          new XAttribute ("name", cat.CategoryName),
          instances.Length==0
          ?
            from c in cat.GetCounters()
            select new XElement ("counter",
              new XAttribute ("name", c.CounterName))
          :
            from i in instances
            select new XElement ("instance", new XAttribute ("name", i),
              !cat.InstanceExists (i)
              ?
                null
              :
                from c in cat.GetCounters (i)
                select new XElement ("counter",
                  new XAttribute ("name", c.CounterName))
            )
        )
      );
    x.Save ("counters.xml");

    讀取性能計(jì)數(shù)器數(shù)據(jù)

    若要檢索性能計(jì)數(shù)器的值,請(qǐng)實(shí)例化性能計(jì)數(shù)器對(duì)象,然后調(diào)用 NextValue 或 NextSample 方法。下一個(gè)值返回一個(gè)簡(jiǎn)單的浮點(diǎn)值;NextSample 返回一個(gè) CounterSample 對(duì)象,該對(duì)象公開(kāi)一組更高級(jí)的屬性,例如 CounterFrequency 、TimeStamp 、BaseValue 和 RawValue 。

    PerformanceCounter 的構(gòu)造函數(shù)采用類別名稱、計(jì)數(shù)器名稱和可選實(shí)例。因此,要顯示所有 CPU 的當(dāng)前處理器利用率,請(qǐng)執(zhí)行以下操作:

    using PerformanceCounter pc=new PerformanceCounter ("Processor",
                                                          "% Processor Time",
                                                          "_Total");
    Console.WriteLine (pc.NextValue());

    或者顯示當(dāng)前進(jìn)程的“真實(shí)”(即私有)內(nèi)存消耗:

    string procName=Process.GetCurrentProcess().ProcessName;
    using PerformanceCounter pc=new PerformanceCounter ("Process",
                                                          "Private Bytes",
                                                          procName);
    Console.WriteLine (pc.NextValue());

    性能計(jì)數(shù)器不會(huì)公開(kāi) ValueChanged 事件,因此如果要監(jiān)視更改,則必須輪詢。在下一個(gè)示例中,我們每 200 毫秒輪詢一次,直到 EventWaitHandle 發(fā)出退出信號(hào):

    // need to import System.Threading as well as System.Diagnostics
    
    static void Monitor (string category, string counter, string instance,
                         EventWaitHandle stopper)
    {
      if (!PerformanceCounterCategory.Exists (category))
        throw new InvalidOperationException ("Category does not exist");
    
      if (!PerformanceCounterCategory.CounterExists (counter, category))
        throw new InvalidOperationException ("Counter does not exist");
    
      if (instance==null) instance="";   // ""==no instance (not null!)
      if (instance !="" &&
          !PerformanceCounterCategory.InstanceExists (instance, category))
        throw new InvalidOperationException ("Instance does not exist");
    
      float lastValue=0f;
      using (PerformanceCounter pc=new PerformanceCounter (category,
                                                          counter, instance))
        while (!stopper.WaitOne (200, false))
        {
          float value=pc.NextValue();
          if (value !=lastValue)         // Only write out the value
          {                               // if it has changed.
            Console.WriteLine (value);
            lastValue=value;
          }
        }
    }

    以下是我們?nèi)绾问褂么朔椒ㄍ瑫r(shí)監(jiān)視處理器和硬盤(pán)驅(qū)動(dòng)器活動(dòng):

    EventWaitHandle stopper=new ManualResetEvent (false);
    
    new Thread (()=>
      Monitor ("Processor", "% Processor Time", "_Total", stopper)
    ).Start();
    
    new Thread (()=>
      Monitor ("LogicalDisk", "% Idle Time", "C:", stopper)
    ).Start();
    
    Console.WriteLine ("Monitoring - press any key to quit");
    Console.ReadKey();
    stopper.Set();

    創(chuàng)建計(jì)數(shù)器和寫(xiě)入性能數(shù)據(jù)

    在寫(xiě)入性能計(jì)數(shù)器數(shù)據(jù)之前,需要?jiǎng)?chuàng)建性能類別和計(jì)數(shù)器。您必須在一個(gè)步驟中創(chuàng)建性能類別以及屬于它的所有計(jì)數(shù)器,如下所示:

    string category="Nutshell Monitoring";
    
    // We'll create two counters in this category:
    string eatenPerMin="Macadamias eaten so far";
    string tooHard="Macadamias deemed too hard";
    
    if (!PerformanceCounterCategory.Exists (category))
    {
      CounterCreationDataCollection cd=new CounterCreationDataCollection();
    
      cd.Add (new CounterCreationData (eatenPerMin,
              "Number of macadamias consumed, including shelling time",
              PerformanceCounterType.NumberOfItems32));
    
      cd.Add (new CounterCreationData (tooHard,
              "Number of macadamias that will not crack, despite much effort",
              PerformanceCounterType.NumberOfItems32));
    
      PerformanceCounterCategory.Create (category, "Test Category",
        PerformanceCounterCategoryType.SingleInstance, cd);
    }

    然后,當(dāng)您選擇“添加計(jì)數(shù)器”時(shí),新計(jì)數(shù)器將顯示在 Windows 性能監(jiān)視工具中。如果以后要在同一類別中定義更多計(jì)數(shù)器,則必須首先通過(guò)調(diào)用 PerformanceCounterCategory.Delete 來(lái)刪除舊類別。

    注意

    創(chuàng)建和刪除性能計(jì)數(shù)器需要管理權(quán)限。因此,它通常作為應(yīng)用程序設(shè)置的一部分完成。

    創(chuàng)建計(jì)數(shù)器后,可以通過(guò)實(shí)例化性能計(jì)數(shù)器、將“只讀”設(shè)置為 false 以及設(shè)置 RawValue 來(lái)更新其值。還可以使用 Increment 和 IncrementBy 方法來(lái)更新現(xiàn)有值:

    string category="Nutshell Monitoring";
    string eatenPerMin="Macadamias eaten so far";
    
    using (PerformanceCounter pc=new PerformanceCounter (category,
                                                           eatenPerMin, ""))
    {
      pc.ReadOnly=false;
      pc.RawValue=1000;
      pc.Increment();
      pc.IncrementBy (10);
      Console.WriteLine (pc.NextValue());    // 1011
    }

    秒表類

    秒表類為測(cè)量執(zhí)行時(shí)間提供了一種方便的機(jī)制。秒表使用操作系統(tǒng)和硬件提供的最高分辨率機(jī)制,通常小于一微秒。(相比之下,DateTime.Now 和 Environment.TickCount 的分辨率約為 15 毫秒。

    要使用秒表,請(qǐng)調(diào)用 StartNew — 這將實(shí)例化秒表并啟動(dòng)它滴答作響。(或者,您可以手動(dòng)實(shí)例化它,然后調(diào)用“開(kāi)始”。已用屬性以 TimeSpan 的形式返回已用間隔:

    Stopwatch s=Stopwatch.StartNew();
    System.IO.File.WriteAllText ("test.txt", new string ('*', 30000000));
    Console.WriteLine (s.Elapsed);       // 00:00:01.4322661

    秒表還公開(kāi)了一個(gè) ElapsedTicks 屬性,該屬性以 long 的形式返回已用的“ticks”數(shù)。要將刻度轉(zhuǎn)換為秒,請(qǐng)除以秒表。還有一個(gè) ElapsedMilliseconds 屬性,它通常是最方便的。

    調(diào)用停止會(huì)凍結(jié)已用和已用的滴答聲。“正在運(yùn)行”的秒表不會(huì)產(chǎn)生后臺(tái)活動(dòng),因此調(diào)用 Stop 是可選的。

    跨平臺(tái)診斷工具

    在本部分中,我們將簡(jiǎn)要介紹可用于 .NET 的跨平臺(tái)診斷工具:

    dotnet-counters

    提供正在運(yùn)行的應(yīng)用程序的狀態(tài)概述

    dotnet-trace

    有關(guān)更詳細(xì)的性能和事件監(jiān)控

    dotnet-dump

    按需或在崩潰后獲取內(nèi)存轉(zhuǎn)儲(chǔ)

    這些工具不需要管理提升,適用于開(kāi)發(fā)和生產(chǎn)環(huán)境。

    dotnet-counters

    工具監(jiān)視 .NET 進(jìn)程的內(nèi)存和 CPU 使用率,并將數(shù)據(jù)寫(xiě)入控制臺(tái)(或文件)。

    若要安裝該工具,請(qǐng)從命令提示符或路徑中帶有 的終端運(yùn)行以下命令:

    dotnet tool install --global dotnet-counters

    然后,您可以開(kāi)始監(jiān)視進(jìn)程,如下所示:

    dotnet-counters monitor System.Runtime --process-id <<ProcessID>>

    System.Runtime 意味著我們要監(jiān)視 類別下的所有計(jì)數(shù)器。可以指定類別或計(jì)數(shù)器名稱(dotnet 計(jì)數(shù)器列表命令列出所有可用的類別和計(jì)數(shù)器)。

    輸出會(huì)不斷刷新,如下所示:

    Press p to pause, r to resume, q to quit.
        Status: Running
    
    [System.Runtime]
        # of Assemblies Loaded                            63
        % Time in GC (since last GC)                       0
        Allocation Rate (Bytes / sec)                244,864
        CPU Usage (%)                                      6
        Exceptions / sec                                   0
        GC Heap Size (MB)                                  8
        Gen 0 GC / sec                                     0
        Gen 0 Size (B)                               265,176
        Gen 1 GC / sec                                     0
        Gen 1 Size (B)                               451,552
        Gen 2 GC / sec                                     0
        Gen 2 Size (B)                                    24
        LOH Size (B)                               3,200,296
        Monitor Lock Contention Count / sec                0
        Number of Active Timers                            0
        ThreadPool Completed Work Items / sec             15
        ThreadPool Queue Length                            0
        ThreadPool Threads Count                           9
        Working Set (MB)                                  52

    以下是所有可用的命令:

    命令

    目的

    列表

    顯示計(jì)數(shù)器名稱列表以及每個(gè)計(jì)數(shù)器名稱的說(shuō)明

    附言

    顯示符合監(jiān)視條件的 dotnet 進(jìn)程的列表

    監(jiān)控

    顯示所選計(jì)數(shù)器的值(定期刷新)

    收集

    將計(jì)數(shù)器信息保存到文件中

    支持以下參數(shù):

    選項(xiàng)/參數(shù)

    目的

    --版本

    顯示的版本。

    -h, --幫助

    顯示有關(guān)程序的幫助。

    -p, --進(jìn)程標(biāo)識(shí)

    要監(jiān)視的 dotnet 進(jìn)程的 ID。適用于監(jiān)視器和收集命令。

    --刷新間隔

    設(shè)置所需的刷新間隔(以秒為單位)。適用于監(jiān)視器和收集命令。

    -o, --輸出

    設(shè)置輸出文件名。適用于收集命令。

    --格式

    設(shè)置輸出格式。有效的是 或 。適用于收集命令。

    dotnet-trace

    跟蹤是程序中事件的時(shí)間戳記錄,例如正在調(diào)用的方法或正在查詢的數(shù)據(jù)庫(kù)。跟蹤還可以包括性能指標(biāo)和自定義事件,并且可以包含局部上下文,例如局部變量的值。傳統(tǒng)上,.NET Framework 和框架(如 ASP.NET)使用 ETW。在 .NET 5 中,應(yīng)用程序跟蹤在 Windows 上運(yùn)行時(shí)寫(xiě)入 ETW,在 Linux 上運(yùn)行時(shí)寫(xiě)入 LTTng。

    若要安裝該工具,請(qǐng)運(yùn)行以下命令:

    dotnet tool install --global dotnet-trace

    若要開(kāi)始記錄程序的事件,請(qǐng)運(yùn)行以下命令:

    dotnet-trace collect --process-id <<ProcessId>>

    這將使用默認(rèn)配置文件運(yùn)行 ,該配置文件收集 CPU 和 .NET 運(yùn)行時(shí)事件并寫(xiě)入名為 的文件。您可以使用 --profile 開(kāi)關(guān)指定其他配置文件:gc-verbose 跟蹤垃圾回收和采樣對(duì)象分配, 以較低的開(kāi)銷跟蹤垃圾回收。-o 開(kāi)關(guān)允許您指定不同的輸出文件名。

    默認(rèn)輸出是一個(gè) 文件,可以使用 PerfView 工具直接在 Windows 計(jì)算機(jī)上進(jìn)行分析。或者,您可以指示創(chuàng)建與Speedscope兼容的文件,Speedscope是 的免費(fèi)在線分析服務(wù)。要?jiǎng)?chuàng)建 Speedscope (.) 文件,請(qǐng)使用選項(xiàng) -。

    注意

    您可以從 下載最新版本的 PerfView。Windows 10 附帶的版本可能不支持 文件。

    支持以下命令:

    命令

    目的

    收集

    開(kāi)始將計(jì)數(shù)器信息記錄到文件中。

    附言

    顯示符合監(jiān)視條件的 dotnet 進(jìn)程的列表。

    列表配置文件

    列出預(yù)生成的跟蹤配置文件,并附有每個(gè)配置文件中的提供程序和篩選器的說(shuō)明。

    轉(zhuǎn)換<文件>

    從 () 格式轉(zhuǎn)換為備用格式。目前,是唯一的目標(biāo)選項(xiàng)。

    自定義跟蹤事件

    你的應(yīng)用可以通過(guò)定義自定義事件源來(lái)發(fā)出自定義事件:

    [EventSource (Name="MyTestSource")]
    public sealed class MyEventSource : EventSource
    {
      public static MyEventSource Instance=new MyEventSource ();
    
      MyEventSource() : base (EventSourceSettings.EtwSelfDescribingEventFormat)
      {
      }
    
      public void Log (string message, int someNumber)
      {
        WriteEvent (1, message, someNumber);
      }
    }

    WriteEvent 方法被重載以接受簡(jiǎn)單類型(主要是字符串和整數(shù))的各種組合。然后可以按如下方式調(diào)用它:

    MyEventSource.Instance.Log ("Something", 123);

    調(diào)用 時(shí),必須指定要記錄的任何自定義事件源的名稱:

    dotnet-trace collect --process-id <<ProcessId>> --providers MyTestSource

    dotnet-dump

    轉(zhuǎn)儲(chǔ)(有時(shí)稱為)是進(jìn)程虛擬內(nèi)存狀態(tài)的快照。您可以按需轉(zhuǎn)儲(chǔ)正在運(yùn)行的進(jìn)程,也可以將操作系統(tǒng)配置為在應(yīng)用程序崩潰時(shí)生成轉(zhuǎn)儲(chǔ)。

    在 Ubuntu Linux 上,以下命令在應(yīng)用程序崩潰時(shí)啟用核心轉(zhuǎn)儲(chǔ)(必要的步驟可能因不同版本的 Linux 而異):

    ulimit -c unlimited

    在 Windows 上,使用 在本地計(jì)算機(jī)配置單元中創(chuàng)建或編輯以下項(xiàng):

    SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps

    在此下,添加一個(gè)與可執(zhí)行文件同名的密鑰(例如 ),并在該密鑰下添加以下密鑰:

    • 轉(zhuǎn)儲(chǔ)文件夾 (REG_EXPAND_SZ),其值指示要將轉(zhuǎn)儲(chǔ)文件寫(xiě)入的路徑
    • 轉(zhuǎn)儲(chǔ)類型 (REG_DWORD),值為 2 以請(qǐng)求完全轉(zhuǎn)儲(chǔ)
    • (可選)DumpCount (REG_DWORD),指示刪除最舊的轉(zhuǎn)儲(chǔ)文件之前的最大轉(zhuǎn)儲(chǔ)文件數(shù)

    若要安裝該工具,請(qǐng)運(yùn)行以下命令:

    dotnet tool install --global dotnet-dump

    安裝后,可以按需啟動(dòng)轉(zhuǎn)儲(chǔ)(不結(jié)束該過(guò)程),如下所示:

    dotnet-dump collect --process-id <<YourProcessId>>

    以下命令啟動(dòng)用于分析轉(zhuǎn)儲(chǔ)文件的交互式 shell:

    dotnet-dump analyze <<dumpfile>>

    如果異常導(dǎo)致應(yīng)用程序關(guān)閉,則可以使用 命令(簡(jiǎn)稱 )顯示該異常的詳細(xì)信息。dotnet-dump shell 支持許多其他命令,您可以使用 命令列出這些命令。

    注冊(cè)表是一個(gè)復(fù)雜的數(shù)據(jù)庫(kù),如果不進(jìn)行維護(hù),它就會(huì)填充損壞的和孤立的注冊(cè)表項(xiàng)。尤其是對(duì)Windows進(jìn)行升級(jí)時(shí),損壞或丟失的注冊(cè)表項(xiàng)也會(huì)不斷累積,從而影響您的系統(tǒng)性能。如果您的Windows 10系統(tǒng)正在經(jīng)歷注冊(cè)表?yè)p壞的問(wèn)題,不妨借助本文給大家介紹的幾種方式進(jìn)行修復(fù),以防止計(jì)算機(jī)的性能不斷受損。下面我們就去深入了解一下修復(fù)方法吧。

    1、借助啟動(dòng)修復(fù)功能

    在較新的Windows系統(tǒng)版本中(比如Windows 10/11等),您可以借助啟動(dòng)修復(fù)功能修復(fù)損壞的注冊(cè)表。具體操作步驟如下:

    步驟1:運(yùn)行計(jì)算機(jī),在左下角搜索框內(nèi)搜索【設(shè)置】程序并打開(kāi)。

    步驟2:接下來(lái),依次找到【更新和安全】-【恢復(fù)】,在【高級(jí)啟動(dòng)】中點(diǎn)擊【立即重新啟動(dòng)】按鈕。

    步驟3:這時(shí),您的系統(tǒng)將運(yùn)行至Windows 恢復(fù)環(huán)境當(dāng)中。接下來(lái)依次點(diǎn)擊【疑難解答】-【高級(jí)選項(xiàng)】-【啟動(dòng)修復(fù)】按鈕。然后計(jì)算機(jī)會(huì)診斷并修復(fù)損壞的注冊(cè)表內(nèi)容,您只需耐心等待該過(guò)程運(yùn)行完成即可。

    2、使用系統(tǒng)文件檢查工具

    系統(tǒng)文件檢查工具(SFC)可以在系統(tǒng)文件目錄中查找和修復(fù)損壞或丟失的系統(tǒng)文件,從而修復(fù)注冊(cè)表?yè)p壞的問(wèn)題。具體操作步驟如下:

    步驟1:運(yùn)行計(jì)算機(jī),在左下角搜索框內(nèi)搜索【cmd】,并選擇【以管理員身份運(yùn)行】打開(kāi)命令提示符工具。若無(wú)法正常進(jìn)入系統(tǒng),您也可以啟用帶命令提示符的安全模式,再進(jìn)行下一步的操作。

    步驟2:在打開(kāi)的命令提示符窗口里,輸入命令【SFC /scannow】并按下【Enter】鍵。接下來(lái)系統(tǒng)文件檢查器會(huì)進(jìn)行系統(tǒng)掃描,并修復(fù)有問(wèn)題的系統(tǒng)文件,比如損壞的注冊(cè)表。修復(fù)完成后,重啟電腦查看問(wèn)題是否已解決。若沒(méi)有解決,請(qǐng)繼續(xù)嘗試下面的方法。

    3、運(yùn)行DISM工具

    DISM是一款微軟官方出品的映像工具。DISM命令通常用于檢查和修復(fù)系統(tǒng)映像文件,并且檢測(cè)和清理注冊(cè)表項(xiàng)目,下面我們就來(lái)學(xué)習(xí)如何使用DISM命令修復(fù)損壞的注冊(cè)表吧。具體操作步驟如下:

    步驟1:運(yùn)行計(jì)算機(jī),在左下角搜索框內(nèi)搜索【cmd】,并選擇【以管理員身份運(yùn)行】打開(kāi)命令提示符工具。若無(wú)法正常進(jìn)入系統(tǒng),您也可以啟用帶命令提示符的安全模式,再進(jìn)行下一步的操作。

    步驟2:在打開(kāi)的命令提示符窗口里,輸入命令【DISM / Online / Cleanup-Image / ScanHealth】并按下【Enter】。等待過(guò)程執(zhí)行完成再查看問(wèn)題是否已解決。

    4、執(zhí)行系統(tǒng)還原

    借助系統(tǒng)還原的方法在于將系統(tǒng)注冊(cè)表還原到注冊(cè)表未損壞前的還原點(diǎn),從而達(dá)到修復(fù)損壞注冊(cè)表的目的。具體操作步驟如下:

    步驟1:運(yùn)行計(jì)算機(jī),在左下角搜索框內(nèi)搜索【控制面板】程序并打開(kāi)。


    步驟2:接下來(lái),在控制面板界面里找到【恢復(fù)】-【開(kāi)始系統(tǒng)還原】選項(xiàng),然后點(diǎn)擊【下一步】。

    步驟3:然后,選中一個(gè)發(fā)生錯(cuò)誤之前最近的還原點(diǎn)進(jìn)行還原,點(diǎn)擊【下一步】等待還原過(guò)程完成即可。

    系統(tǒng)還原的前提是已經(jīng)創(chuàng)建了還原點(diǎn),如果沒(méi)有創(chuàng)建還原點(diǎn),還可以嘗試重置電腦,同時(shí)保存?zhèn)€人文件的方法。

網(wǎng)站首頁(yè)   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有