我有这段代码:
ManualResetEvent EventListenerStopped;
...
while (true)
{
IAsyncResult iar = this.ListenerHttp.BeginGetContext(ProcessRequest, null);
if (WaitHandle.WaitAny(new[] { this.EventListenerStopped, iar.AsyncWaitHandle }) == 0)
return;
}
基本上它等待两个事件中的任何一个:
此代码已经在生产中运行了很长时间。
我想尝试将其转换为新的await / async机制,但似乎无法找到一种简单的方法。
我尝试使用布尔值,调用者可以转为false。它显然不起作用,因为它只在收到并处理新请求后才退出循环:
bool RunLoop;
...
while (this.RunLoop)
{
HttpListenerContext listenerContext = await this.ListenerHttp.GetContextAsync();
ProcessRequest(listenerContext);
}
我想知道是否甚至可以用async / await重写我简单的旧式循环。如果是的话,有人会愿意告诉我怎么做?
答案 0 :(得分:0)
它并不特定于async-await,但您可能正在寻找CancellationToken
(无论如何都会使用大量的async-await代码):
http://blogs.msdn.com/b/pfxteam/archive/2009/05/22/9635790.aspx
' BlockingOperation'示例代码与您尝试执行的操作类似:
void BlockingOperation(CancellationToken token) { ManualResetEvent mre = new ManualResetEvent(false); //register a callback that will set the MRE CancellationTokenRegistration registration = token.Register(() => mre.Set()); using (registration) { mre.WaitOne(); if (token.IsCancellationRequested) //did cancellation wake us? throw new OperationCanceledException(token); } //dispose the registration, which performs the deregisteration. }
答案 1 :(得分:0)
首先,我必须指出旧代码不太正确。处理Begin
/End
pattern时,必须始终呼叫End
,即使您希望(或确实)取消操作。 End
通常用于处置资源。
如果您确实想要取消,CancellationToken
可能是最佳方法:
while (true)
{
// Throws an OperationCanceledException when cancellationToken is canceled.
var request = await this.ListenerHttp.GetContextAsync(cancellationToken);
ProcessRequest(request);
}
还有其他选择 - 可能执行类似Task.WhenAny
的操作,甚至还有AsyncManualResetEvent
的实现,因此可以逐行创建相当于旧代码,但IMO取消令牌方法会更清晰。
例如,使用AsyncManualResetEvent
from my AsyncEx library:
AsyncManualResetEvent eventListenerStopped;
while (true)
{
var task = GetContextAndProcessRequestAsync();
if (await Task.WhenAny(eventListenerStopped.WaitAsync(), task) != task)
return;
}
async Task GetContextAndProcessRequestAsync()
{
var request = await this.ListenerHttp.GetContextAsync();
ProcessRequest(request);
}
但就个人而言,我会改为使用CancellationToken
。