2013-03-13 30 views
9

我正在寫一個非常簡單的實用程序類,目的是測量任何傳入的方法(任何類型)所執行的時間。如何計算實用程序類別的方法已過去的時間

在我的情況下Membership.ValidateUser(model.UserName, model.Password)返回布爾,所以我得到一個異常。

我想如果可能的話寫一個這種類型的實用程序類的代碼示例如何解決它。 它是否有意義使用動態而不是行動?

Tracing.Log(Membership.ValidateUser(model.UserName, model.Password), "Membership.ValidateUser"); 

public static class Tracing 
     { 
      public static void Log(Action action, string message) 
      { 
       // Default details for the Log 
       string sSource = "TRACE"; 
       string sLog = "Application"; 

       // Create the Log 
       if (!EventLog.SourceExists(sSource)) 
        EventLog.CreateEventSource(sSource, sLog); 

       // Measure time Elapsed for an Action 
       Stopwatch stopwatch = Stopwatch.StartNew(); 
       action(); 
       stopwatch.Stop(); 
       TimeSpan timeElapsed = stopwatch.Elapsed; 

       // Write the Log 
       EventLog.WriteEntry(sSource, "TIME-ELAPSED: " + timeElapsed .ToString() + message, EventLogEntryType.Warning, 234); 
      } 
     } 

回答

8

您當前的代碼試圖執行ValidateUser和使用結果作爲方法的參數。你想通過而不是首先執行ValidateUser

你只需要你的方法調用轉換爲使用lambda表達式來創建一個委託:(動態類型不會影響這個在所有)

Tracing.Log(() => Membership.ValidateUser(model.UserName, model.Password), 
      "Membership.ValidateUser"); 

注意定時單方法執行通常會給你帶來非常嘈雜的結果,除非它是一個相當長的方法調用。通常要基準測試多次執行該方法的單個方法,直到您花費相當多的時間執行該方法。使用Stopwatch有幫助,但它不會超過您的方法可能需要非常少的刻度才能完成的事實,並且如果線程已被預先佔用,那麼結果將產生不成比例的影響。

編輯:我假設你想純粹用於基準測試。如果你想在你的真實應用程序中進行這種跟蹤,你需要一種侵入性較小的方法。例如,看看Mini-MVC-Profiler

+0

我想感謝您的解釋。怎麼可能重寫我的課程,並在內部使用labda?感謝您的時間 – GibboK 2013-03-13 12:38:53

+0

@GibboK:我不知道你的意思。我已經向您展示瞭如何調用該方法。 – 2013-03-13 12:41:08

+0

感謝Jon,我不知道MVC-Profiler。 – GibboK 2013-03-13 12:44:27

0

沒有違法意圖,但你的設計方法似乎落後於我。我假設您的業務目標更多地是關於驗證用戶的時間代碼操作。如果這不正確,請不理我。 :)

如果我是你,我會注入一個時間/跟蹤類到你的驗證,而不是其他的方式。您可以使用任何方式(框架之一或簡單的構造函數注入)來使用依賴注入,並在提供時使用它來執行時序。

HTH

+1

儘管想要跟蹤實時流量是很好的,但它對於能夠純粹爲了基準測試而行使一種方法也很有用。 – 2013-03-13 12:37:27

+0

是的,我只需要一個快速的方式來跟蹤實時流量 – GibboK 2013-03-13 12:42:46

+0

沒有爭論,但我不明白爲什麼要卸載執行一個動作或Func的責任(什麼發生在OP的願望讓布爾回來?)到一個助手類。那麼,如果你想使用_otherother_ helper類設計相同的方式來提供性能指標呢? ValidateUser已經在之前的調用中運行過.. IDK .. – 2013-03-13 12:47:56

0

如果你可以修改被測量的方法,你可以引入一個類在它的創作,將啓動計時器,並停止出售。而且,如果超過某個閾值,它會創建一個日誌消息

用法是:

using(var tm = new TimeMeasurementThreshold(TimeSpan.FromSeconds(1),"Sending mail block",logger)){ 
// measured code here 
} 

public class TimeMeasurementThreshold : IDisposable 
    { 
     private readonly Logger logger; 

     private readonly TimeSpan thresholdTime; 

     private readonly string codeBlockName; 

     private readonly TimeMeasurement timeMeasurement; 

     public TimeMeasurementThreshold(TimeSpan thresholdTime, string codeBlockName, Logger logger) 
     { 
      this.logger = logger; 
      this.thresholdTime = thresholdTime; 
      this.codeBlockName = codeBlockName; 

      timeMeasurement = new TimeMeasurement(); 
     } 

     public void Dispose() 
     { 
      TimeSpan elapsed = timeMeasurement.Elapsed; 

      if (elapsed >= thresholdTime) 
      { 
       logger.Debug("{0} execution time is {1:N0}ms", codeBlockName, elapsed.TotalMilliseconds); 
      } 
     } 
    } 
0

您可以輕鬆地使用lambda來指定動作,你傳遞給另一個方法的結果,例如:

using System; 

namespace Demo 
{ 
    public static class Program 
    { 
     private static void Main(string[] args) 
     { 
      bool result = false; 

      Tracing.Log(() => 
      { 
       result = test(""); // Assign to result. 
      }, "Message"); 

      Console.WriteLine(result); 
     } 

     private static bool test(string value) 
     { 
      return string.IsNullOrEmpty(value); 
     } 
    } 

    public static class Tracing 
    { 
     public static void Log(Action action, string message) 
     { 
      action(); 
      Console.WriteLine(message); 
     } 
    } 
}