Do czego potrzebny jest czas oczekiwania?
Domyślna klasa dla "czegoś, na co mogę czekać" w .NET to System.Threading.Tasks.Task
. W .NET 4.5 możesz po prostu użyć Task.Delay(milliseconds)
.
W .NET 4.0 można użyć TaskCompletionSource
, aby utworzyć zadanie i ustawić je jako zakończone przy użyciu zwykłego zegara. Lub użyj realizację TaskEx.Delay
z Async Targeting Pack lub AsyncBridge
Jeśli potrzebujesz rzeczywistego WaitHandle
, można użyć ManualResetEvent
i użyć zwykłego .NET timer ustawiony zdarzenia.
Można również utworzyć własną klasę pochodną od WaitHandle
i P/Invoke CreateWaitableTimer
. Wygląda na to, że taka klasa istnieje już w środowisku .NET, ale jest wewnętrzna. (System.Runtime.IOThreadTimer.WaitableTimer
z 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();
}
}
}
muszę go umieścić w funkcji oczekiwania (które będą czekać na wielu obiektach. Imprezy i jeden z nich jest timer) Rozumiem, że mogę to zrobić za pomocą funkcji wywołania zwrotnego, ale wymagałoby to przeprojektowania mojego kodu. Tak, tak, wydaje się, że będę musiał iść z Win32 API i P/Invoke. Po prostu nie jestem dobry w robieniu tego materiału P/Invoke ... Oto link, który znalazłem: http://www.anotherchris.net/csharp/wake-up-from-sleep-createwaitabletimer-in-csharp/ – c00000fd
Ten link wygląda mi dobrze; z tą różnicą, że użyłbym niestandardowej klasy pochodnej 'WaitHandle' zamiast' EventWaitHandle'. Kod w łączu kończy się tworzeniem nieużywanego 'AutoResetEvent'. – Daniel
Dzięki. Jedną z kwestii, której doświadczyłem, jest to, że jeśli utworzę powtarzający się timer (lub gdy trzeci parametr 'SetWaitableTimer' nie jest równy 0), wywołanie pierwszego' wh.WaitOne() 'działa, ale jeśli zadzwonię ponownie, to doesn ' t czekaj na czas licznika. Każdy pomysł, dlaczego? – c00000fd