2013-04-07 5 views

risposta

6

Per cosa serve il timer?

La classe predefinita per "qualcosa che posso aspettare" in .NET è System.Threading.Tasks.Task. In .NET 4.5, puoi semplicemente usare Task.Delay(milliseconds).

In .NET 4.0, è possibile utilizzare un TaskCompletionSource per creare un'attività e impostarlo come completato utilizzando un normale timer. Oppure utilizzare il TaskEx.Delay implementazione della Async Targeting Pack o AsyncBridge

Se avete bisogno di un vero e proprio WaitHandle, è possibile utilizzare un ManualResetEvent, e utilizzare un normale timer NET per impostare l'evento.

In alternativa, è possibile creare la propria classe derivata da WaitHandle e P/Invoke CreateWaitableTimer. Sembra che tale classe esista già nel framework .NET, ma è interna. (System.Runtime.IOThreadTimer.WaitableTimer da System.ServiceModel.Internals.dll)

public class WaitableTimer : WaitHandle 
{ 
    [DllImport("kernel32.dll")] 
    static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, [MarshalAs(UnmanagedType.Bool)] bool fResume); 

    public WaitableTimer(bool manualReset = true, string timerName = null) 
    { 
     this.SafeWaitHandle = CreateWaitableTimer(IntPtr.Zero, manualReset, timerName); 
    } 

    public void Set(long dueTime) 
    { 
     if (!SetWaitableTimer(this.SafeWaitHandle, ref dueTime, 0, IntPtr.Zero, IntPtr.Zero, false)) 
     { 
      throw new Win32Exception(); 
     } 
    } 
} 
+1

ho bisogno di includere in una funzione di attesa (che attende la più oggetti:. Eventi e uno di loro è un timer) ho capito che posso fare questo con una funzione di callback, ma ciò richiederebbe una riprogettazione del mio codice. Quindi, sì, sembra che dovrò andare con Win32 API e P/Invoke. Non sono molto bravo a fare questa roba P/Invoke ... Ecco il link che ho trovato: http://www.anotherchris.net/csharp/wake-up-from-sleep-createwaitabletimer-in-csharp/ – c00000fd

+1

Quel collegamento mi sembra buono; tranne che userei una classe personalizzata 'WaitHandle' invece di' EventWaitHandle'. Il codice nel collegamento finisce per creare un 'AutoResetEvent' inutilizzato. – Daniel

+0

Grazie. Un problema che ho riscontrato è che se creo un timer ripetuto (o quando il terzo parametro di 'SetWaitableTimer' non è 0), chiamando il primo' wh.WaitOne() 'funziona, ma se lo chiamo di nuovo, non lo fa t attendere il periodo del timer. Qualche idea del perché? – c00000fd