Social Icons

miércoles, 3 de octubre de 2012

Un Thread.Sleep que no cuelga el hilo

He estado añadiendo tests unitarios a mi código de SharePoint y no es una tarea facil.

Una de las cosas más importantes que quería probar eran unos ItemEventReceivers de una lista. Esto funciona sin problemas cuando pruebas los eventos síncronos como el ItemAdding o el ItemUpdating pero cuando se trata de probar los eventos asíncronos es necesario esperar...

Si pones el hilo del test a dormir los eventos asíncronos no se ejecutarán ya que es el mismo en el que se ejecuta el código de SharePoint y aunque tu código funcione cuando lo ejecutas a mano los tests fallarán.

Es por esto que he creado una clase basada en timers que no cuelga el hilo dejando ejecutarse los eventos asíncronos.
  1. public class Waiter : IDisposable  
  2. {  
  3.     public enum WaiterState  
  4.     {  
  5.         Waiting,  
  6.         TimedOut,  
  7.         Success,  
  8.         Error  
  9.     };  
  10.   
  11.     System.Timers.Timer WaitTimer;  
  12.     ManualResetEvent manualResetEvent;  
  13.     int WaitCounter;  
  14.   
  15.     private Waiter(int interval)  
  16.     {  
  17.         WaitCounter = 0;  
  18.   
  19.         manualResetEvent = new ManualResetEvent(true);  
  20.         WaitTimer = new System.Timers.Timer() { AutoReset = false, Interval = interval };  
  21.         WaitTimer.Elapsed += new ElapsedEventHandler(WaitTimer_Elapsed);  
  22.     }  
  23.   
  24.     void WaitTimer_Elapsed(object sender, ElapsedEventArgs e)  
  25.     {  
  26.         WaitCounter++;  
  27.         manualResetEvent.Set();  
  28.     }  
  29.   
  30.     /// <summary>  
  31.     /// Waits for the interval in milliseconds times number of times or once by default.  
  32.     /// </summary>  
  33.     public static WaiterState Wait(int interval, int times)  
  34.     {  
  35.         try  
  36.         {  
  37.             using (Waiter WaiterClass = new Waiter(interval))  
  38.             {  
  39.                 while (WaiterClass.WaitCounter <= times)  
  40.                 {  
  41.                     WaiterClass.WaitTimer.Start();  
  42.                     WaiterClass.manualResetEvent.WaitOne();  
  43.                 }  
  44.             }  
  45.         }  
  46.         catch  
  47.         {  
  48.             return WaiterState.Error;  
  49.         }  
  50.   
  51.         return WaiterState.Success;  
  52.     }  
  53.   
  54.     /// <summary>  
  55.     /// Waits for the interval in milliseconds once.  
  56.     /// </summary>  
  57.     public static WaiterState Wait(int interval)  
  58.     {  
  59.         return Wait(interval, 0);  
  60.     }  
  61.   
  62.     void Dispose()  
  63.     {  
  64.         WaitTimer.Dispose();  
  65.     }  
  66. }  
Pruébala.

No hay comentarios:

Refrescando el SharePoint 2010 Timer Service mediante código

Necesito refrescar el servicio de Timer desde una aplicación y me ha costado bastante encontrar cómo hacerlo. Es tan facil como te imaginas

Aquí está el código:
  1. /// <summary>  
  2. /// Stops the SharePoint timer.  
  3. /// </summary>  
  4. public static void TimerStop()  
  5. {  
  6.     ServiceController timerService = new ServiceController(Constants.SPTimerName);  
  7.   
  8.     if (timerService.Status == ServiceControllerStatus.Running)  
  9.     {  
  10.         timerService.Stop();  
  11.         timerService.WaitForStatus(ServiceControllerStatus.Stopped, Constants.WaitingTimeout);  
  12.     }  
  13. }  
  14.   
  15. /// <summary>  
  16. /// Starts the SharePoint timer.  
  17. /// </summary>  
  18. public static void TimerStart()  
  19. {  
  20.     ServiceController timerService = new ServiceController(Constants.SPTimerName);  
  21.   
  22.     if (timerService.Status == ServiceControllerStatus.Stopped)  
  23.     {  
  24.         timerService.Start();  
  25.         timerService.WaitForStatus(ServiceControllerStatus.Running, Constants.WaitingTimeout);  
  26.     }  
  27. }  
Por cierto, las constantes son:
  1. public static TimeSpan WaitingTimeout = new TimeSpan(0, 1, 30);  
  2. public static string SPTimerName = "SharePoint 2010 Timer";  

No hay comentarios: