2016-01-17 29 views
-1

我有这样的代码:等待任何异步方法和(事件或布尔)

ManualResetEvent EventListenerStopped; 
... 
while (true) 
{ 
    IAsyncResult iar = this.ListenerHttp.BeginGetContext(ProcessRequest, null); 
    if (WaitHandle.WaitAny(new[] { this.EventListenerStopped, iar.AsyncWaitHandle }) == 0) 
     return; 
} 

基本上它等待任何两个事件:

  • 如果接收到请求时,它对其进行处理和等待下一个。
  • 如果引发EventListenerStopped,它将退出循环。

这段代码现在已经很好地运行在生产中了。

我想尝试将其转换为新的await/async机制,似乎无法找到一个很好的简单方法来完成它。

我试着用一个布尔值调用者可以变成false。/

bool RunLoop; 
... 
while (this.RunLoop) 
{ 
    HttpListenerContext listenerContext = await this.ListenerHttp.GetContextAsync(); 
    ProcessRequest(listenerContext); 
} 

我想知道如果它甚至有可能改写我简单的旧式环路与异步等待:这很明显,因为它退出新的请求已被接收后,才和处理循环不起作用。如果是的话,有人愿意告诉我如何?

+0

您是否试图阻止侦听器而不是使用bool? – alexm

+0

@Micky我明白他们不一样。我的观点是:有没有一种方法可以实现类似于异步/等待的方式(我很困惑地想到某种Task.WaitAny(),其中一个任务将检查某些布尔值的提升......) – user1409737

+0

@alexm我自己没有尝试过,但是在SO上读了一些地方,不应该这样做,因为它会破坏当前处理的任何请求(并且ListenerContext对象被传递到线程池以在我的情况下进行处理...) – user1409737

回答

0

这不是专门针对异步的await,但你可能寻找CancellationToken(其中使用了大量的异步等待代码反正):

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. 
} 
+0

我阅读了有关CancellationToken的信息,我同意这可以做到这一点。然而,它似乎比我目前的两行代码复杂得多。我慢慢地得出结论异步/等待并不总是一个更好的方式来做事情... – user1409737

+0

我倾向于同意。现在我非常多地使用异步等待所有IO绑定的东西,但我仍然发现你想要替换的模式在某些情况下很有用,特别是对于单独线程的工作者方法。我不知道你的代码的完整上下文,但它可能是一个例子,它不一定是一个好主意,因为它是新事物而使用异步等待。 – sellotape

+0

(我正好在一个单独的工作线程的情况下)谢谢你分享你的想法! – user1409737

0

首先,我必须指出,旧的代码非q正确的。在处理Begin/End pattern时,即使您想(或确实)取消操作,您的必须始终呼叫EndEnd通常用于处理资源。

如果你想使用取消,一个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