我需要能夠等待一個事件,但也能夠在呼叫取消后終止等待。
我AutoResetEvent用作等待信號繼續作業的一種方式。為了能夠取消等待,我想出了兩個解決方案:
- 注冊一個
CancellationToken.Register將設定的委托AutoResetEvent。 - 使用
TaskCompletionSource. 但是,由于我不能重用TaskCompletionSource,所以我想出了TaskCompletionSource每次觸發新事件時排隊 new 的解決方案。
這些是正確的解決方案還是有更優雅的方法來做到這一點?
解決方案 1
class MyClass
{
AutoResetEvent _dataArrivedSignal = new AutoResetEvent (false);
public Task RunAsync(CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() =>
{
cancellationToken.Register(() => _dataArrivedSignal.Set());
while(condition)
{
DoSomeWork();
_dataArrivedSignal.WaitOne();
cancellationToken.ThrowIfCancellationRequested();
}
}
}
private void OnDataArrived(EventArgs args)
{
_dataArrivedSignal.Set();
}
}
解決方案 2
class MyClass
{
ConcurrentQueue<TaskCompletionSource> _awaiters = new ConcurrentQueue<TaskCompletionSource>();
TaskCompletionSource _waiter;
public MyClass3()
{
_waiter = new TaskCompletionSource();
_awaiters.Enqueue(_waiter);
}
public Task RunAsync(CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() =>
{
while(condition)
{
DoSomeWork();
_awaiters.TryDequeue(out TaskCompletionSource waiter);
waiter.Task.Wait(cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
}
}
}
private void OnDataArrived(EventArgs args)
{
var newWaiter = new TaskCompletionSource();
_awaiters.Enqueue(newWaiter);
_waiter.SetResult();
_waiter = newWaiter;
}
}
uj5u.com熱心網友回復:
是的,還有更優雅的方式。請注意,AutoResetEvent繼承自WaitHandle. CancellationToken反過來有財產WaitHandle,描述為:
獲取在取消令牌時發出信號的 WaitHandle。
然后,WaitHandle有一個靜態方法WaitAny,它接受等待句柄陣列,并在發出信號的第一個等待句柄陣列中回傳一個索引。
所以要實作你想要的 - 使用:
public Task RunAsync(CancellationToken cancellationToken) {
return Task.Factory.StartNew(() => {
while (condition) {
DoSomeWork();
int signaled = WaitHandle.WaitAny(new[] { _dataArrivedSignal, cancellationToken.WaitHandle });
if (signaled == 0) {
// your _dataArrivedSignal was signaled
}
else {
// cancellation token was signaled
}
}
});
}
WaitAnyWaitOne如果您在實際代碼中實際使用超時,也可以接受超時。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/523577.html
標籤:C#异步异步等待
上一篇:如何執行代碼,同時承諾正在解決
