2015-10-15 3 views
5

Я должен отсутствовать что-то очевидное, как тупик на SynchronizationContext, но я не понимаю, почему это происходит, и не понимаю, как я могу избежать этого ...Task.WaitAll висит с асинхронным/ждут задания

Итак, приложение Azure WorkerRole (по сути, насколько я понимаю, обычное приложение Windows без интерфейса). В приложении я пытаюсь параллельно выполнение целого ряда задач и схематической версия моего кода заключается в следующем:

private async Task DoJob() 
{ 
    await SomeIoOperation(); 
} 


public void MethodExecutedByWorkerRoleInAnInfiniteLoop() 
{ 
    Log("Start"); 
    Task.WaitAll(DoJob(), DoJob(), DoJob()); 
    Log("End"); 
} 

Моей идея здесь заключается в том, что мы работаем с невыполнением SynchronizationContext здесь, так что мы должны избегать тупик, который мы имели бы в подобной ситуации, например, в ASP.NET.

Однако иногда Выполнение зависания - Запуск регистрируется, Конец не в течение нескольких дней, пока я не перезапущу роль рабочего. Естественно, что DoJob не может работать так долго. Как ни странно, это происходит не сразу после запуска роли рабочего - это может занять несколько дней или недель нормальной работы, пока оно не зависает.

Я мог бы слишком упростить код - возможно, важно, что именно происходит в SomeIoOperation - но я чувствую, что это что-то очевидное, связанное с неправильным использованием SynchronizationContext.

Will SomeIoOperation.ConfigureAwait(false) help? Я даже не могу его проверить, потому что я не знаю, работает ли он, потому что проблема исправлена ​​или в конечном итоге будет висеть через несколько дней.

Идеи?

+1

Эта статья освещает вас по причине http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – Gusdor

+2

Добавить в 'Log (SynchronizationContext.Current);' и if это не 'null', вы бы знали, что у вас есть проблема с' SynchronizationContext'. – i3arnon

+0

'DoJob' всегда хочет синхронизировать с вызывающим контекстом. Не имеет значения, какой контекст использует 'SomeIoOperation'. – Gusdor

ответ

8

Вы точно зашли в тупик в SynchronizationContext. Просто используйте WhenAll вместо WaitAll:

public async Task MethodExecutedByWorkerRoleInAnInfiniteLoop() 
{ 
    Log("Start"); 
    await Task.WhenAll(DoJob(), DoJob(), DoJob()); 
    Log("End"); 
} 

и все будет работать.

+1

Этот метод выполняется в цикле - вызывающий должен знать, когда метод завершился. ИМО, эта ревизия должна возвращать 'Задача'. – Gusdor

+0

Спасибо. Я просто забываю изменить void на Task. –

+0

Но тогда в моем цикле мне придется делать 'MethodExecutedByWorkerRoleInAnInfiniteLoop(). Wait()' - не будет ли он заторможен? Насколько я знаю, нет версии async 'RoleEntryPoint' в' Microsoft.WindowsAzure.ServiceRuntime', поэтому я не смогу ждать своего метода MethodExecutedByWorkerRoleInAnInfiniteLoop. –

Смежные вопросы