2015-03-26 3 views
0

У меня есть роль рабочего Azure, которая читает сообщения из очереди служебной шины, используя директиву для сообщений об ошибке .Azure WorkerRole API Calls async/await

Вот пример код:

public override void Run() 
{ 
    Client.OnMessage((receivedMessage) => { 

     var APIResponse = Call3rdPartyAPIUsingMessageData(receivedMessage) 

    }, options); 

} 

Вопрос заключается в том, что третий вызов стороны API занимает много времени. Кажется глупым сидеть и ждать, пока вызов API завершится синхронно.

Что бы я хотел, это использовать async/await, чтобы сохранить тему. Смысл, я хочу, чтобы рабочая роль «приостанавливала это сообщение» и обрабатывала следующее сообщение в очереди. Когда вызов API третьей стороны завершается, вернитесь назад и завершите операцию.

Рассматривая другие ответы на stackoverflow (например: here), кажется, что использование функции async/await в роли рабочего - это не очень хорошая идея.

Какие у меня варианты?

+1

Посмотрите на TPL DataFlow. –

+0

Интересно. В лазурном режиме какое приложение/сервис/webjob/etc будет использовать TPL DataFlow. –

+0

Сколько одновременных вызовов вы хотели бы сделать на служебной шине? –

ответ

0

Роли рабочих созданы для выполнения длительных задач обработки. Это одна из причин, по которой они созданы.

Если вы хотите сделать другой (и умный) approuch, попробуйте paralls: http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx

Таким образом, вы можете быть в состоянии обрабатывать данные одновременно, и, конечно, иметь более быстрый результат.

0

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

Вы смотрите на проблему с неправильным углом. Используемый вами ServiceBus QueueClient имеет параметр MaxConcurrentCalls, который устанавливает, сколько потоков будет использоваться при подключении к SB. Каждый раз, когда вы вызываете OnMessage, используется новый поток, пока вы не достигнете порога MaxConcurrentCalls. Таким образом, это уже масштабируется до точки

Что вы хотите сделать, это код, который вызывает асинхронный API (например, путем его переноса в Task), а не в OnMessage, поскольку нет смысла делать это.

EDIT: Что я забыл упомянуть, и это, пожалуй, лучший способ - использовать OnMessageAsync, если у вас есть работа с привязкой к I/O, так же, как вызов API в вашем случае.

+0

Чтобы вызвать вызовы API async - вы хотели бы использовать термин 'await'. Для этого вам нужно сделать 'Main()' async. Вы не можете выполнить 'Main()' метод 'async'. Изменить: вы могли бы, но затем метод 'Main()' отключается, а рабочая роль перезапускается - убивает ваш запрос асинхронного запроса. –

+0

Асинхронный не обязательно означает ключевое слово async. Асинхронный означает, что обработка происходит без блокировки потока. Это также можно сделать, например Task.FromResult (() => YourAppiCall) .ContinueWith (nextmethod()); и т. д., пока вы не хотите возвращать результат в основную нить, вы просто запускаете его и забываете. –

+0

Я также забыл упомянуть, что вам не нужно использовать OnMessage, который является синхронным. Вы можете использовать OnMessageAsync, который является наиболее подходящим способом. –