2013-03-13 16 views
9

Piszę bardzo prostą klasę użytkową, której celem jest pomiar czasu wykonanego dla każdej metody przekazanej (dowolnego typu).Jak liczyć czas, jaki upłynął dla metody z klasą użyteczności

W moim przypadku Membership.ValidateUser(model.UserName, model.Password) return bool, więc otrzymuję wyjątek.

Chciałbym, jeśli byłoby to możliwe, napisać klasę użytkową tego typu, próbkę kodu, jak to naprawić. Czy ma sens korzystanie z dynamiki zamiast działania?

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

Odpowiedz

8

Twój aktualny kod usiłuje wykonać ValidateUser i użyć wynik jako metoda argumentu. Chcesz przekazać akcję bez najpierw wykonując ValidateUser.

Wystarczy zamienić wywołanie metody użyć wyrażenia lambda do tworzenia delegata (. Dynamiczne typowanie nie wpłynie to w ogóle)

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

Należy zauważyć, że pojedynczy rozrządu wykonanie metody często daje bardzo hałaśliwe wyniki, chyba że jest to rozsądnie długie wywołanie metody. Zazwyczaj do testowania pojedynczej metody chcesz wykonać tę metodę wiele razy, aż wydasz rozsądnie dużo czasu na jej wykonanie. Korzystanie z pomocy Stopwatch pomaga, ale nie pomija faktu, że twoja metoda może wymagać wykonania bardzo niewielu tyknięć, a jeśli wątek zostanie uprzedzony, będzie to miało nieproporcjonalny wpływ na wyniki.

EDYCJA: Zakładam, że chcesz użyć tego wyłącznie do testów porównawczych. Jeśli próbujesz wykonać to śledzenie w swojej prawdziwej aplikacji, będziesz potrzebował mniej inwazyjnego podejścia. Na przykład spójrz na Mini-MVC-Profiler.

+0

Chciałbym podziękować za wyjaśnienie. W jaki sposób można przepisać moją klasę i sprawić, by korzystanie z labdy było w środku? dziękuję za poświęcony czas – GibboK

+0

@ GibboK: Nie wiem o co ci chodzi. Pokazałem ci, jak możesz wywołać tę metodę. –

+0

Dzięki Jon, nie wiedziałem o MVC-Profiler. – GibboK

0

Bez zamiaru, ale twoje podejście do projektowania wydaje mi się zacofane. Zakładam, że twoje cele biznesowe polegają bardziej na sprawdzeniu poprawności użytkownika niż na operacjach kodowania w czasie. Jeśli to jest niewłaściwe, zignoruj ​​mnie. :)

Gdybym był tobą, wprowadziłbym klasę wyczucia/śledzenia do twojego sprawdzania poprawności zamiast na odwrót. Można użyć zastrzyku zależności na wiele sposobów (jedną z frameworków lub zwykłego wtrysku konstruktora) i użyć go do wykonania pomiaru czasu, jeśli został dostarczony.

HTH

+1

Chociaż dobrze jest śledzić ruch na żywo, to * również * możesz używać metody wyłącznie w celu jej porównania. –

+0

Tak Po prostu potrzebuję szybkiego sposobu śledzenia ruchu na żywo – GibboK

+0

Bez kłótni, ale nie rozumiem, dlaczego ktoś mógłby odrzucić odpowiedzialność za wykonanie Akcji lub Func (co stało się z wolą PO, aby odzyskać Bool?) klasa pomocnika. Co jeśli, powiedzmy, chciałbyś użyć klasy _another_ helper zaprojektowanej w ten sam sposób, aby dostarczyć dane profilowania? ValidateUser już działał we wcześniejszej rozmowie .. IDK .. –

0

Jeśli można zmodyfikować metodę, która jest mierzona, można wprowadzić klasę, która rozpocznie timera w to tworzenie i zatrzymać go na dyspozycji. A jeśli jakiś próg zostanie przekroczony, to utworzyć wiadomość dziennika

Wykorzystanie będą:

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

można łatwo używać lambda przypisać wynik działania, które przechodzą do innego sposobu, przykład:

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); 
     } 
    } 
} 
Powiązane problemy