2016-01-17 5 views
-1

У меня есть этот код:ждут какого-либо метод асинхронных и (событие или логический)

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

В основном он ждет любого из двух событий:

  • если запрос получен, он обрабатывает его и дождитесь следующего.
  • если EventListenerStopped поднят, он выходит из цикла.

Этот код работает в производстве красиво уже довольно давно.

Я хотел попробовать и преобразовать его в новый механизм ожидания/асинхронности и, похоже, не может найти хороший простой способ сделать это.

Я попробовал с булевым, вызывающий может обратиться к false. Это, очевидно, не работает, как он выходит из цикла только после того, как новый запрос был получен и обработан:

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

Я интересно, если это возможно даже переписать мой простой цикл в старом стиле с асинхронным/ждут. Если да, хотел бы кто-нибудь показать мне, как это сделать?

+0

Вы пытались остановить слушателя вместо использования bool? – alexm

+0

@ Мики Я понимаю, что они не то же самое. Я имел в виду: есть ли способ достичь чего-то подобного с async/await (я смущенно думал о какой-то Task.WaitAny(), где одна из задач будет проверять повышение некоторых логических ...) – user1409737

+0

@alexm Я сам не пробовал, но читал где-то на SO, что это не должно быть сделано, поскольку оно нарушит любой обработанный запрос (ну, объект ListenerContext передается в threadpool для обработки в моем случае ...) – user1409737

ответ

0

Это не относится к асинхронным-ОЖИДАНИЕ, но вы, вероятно, ищет 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

Я склонен согласиться. В наши дни я довольно часто использую async-ждут исключительно для всех объектов, связанных с IO, но я все еще нахожу шаблон, который вы пытаетесь заменить полезным в некоторых случаях, особенно для рабочего метода для отдельного потока. Я не знаю полного контекста вашего кода, но это вполне может быть примером, где не обязательно хорошая идея использовать async-wait только потому, что это новая вещь. – sellotape

+0

(Я как раз в случае отдельного рабочего потока) Спасибо, что поделились своими мыслями! – user1409737

0

Ну, во-первых, я должен отметить, что старый код не д uite правильно. Когда вы работаете с 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, так можно создать почти по очереди эквивалент старого кода, но ИМО подход маркера отмены будет более чистым.

Например, с помощью 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.