Ожидание нескольких асинхронных запросов POST - PullRequest
6 голосов
/ 12 ноября 2010

Мне нужно сделать несколько асинхронных вызовов изнутри службы wcf, размещенной в IIS (может быть, это актуально, я не знаю). Звонки в другие сервисы, но я делаю их, помещая строку в URL сервиса. Вызов их синхронно работает, но у меня более десятка вызовов, и они полностью независимы, поэтому я хотел бы ускорить их, вызывая их асинхронно.

Теперь я понимаю, что я мог бы просто использовать несколько потоков для этого - и это могло бы быть самым простым решением - но я решил попробовать async.

Мой код похож на это:

public delegate void Callback(string response);

public static void InvokeAsync(string request, string url, Callback callback)
  where TResponse: class
{
  var web = new WebClient();
  web.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

  web.UploadStringCompleted += (sender, e) => callback.Invoke(e.Result);
  web.UploadStringAsync(new Uri(url), request);
}

//...
var lockObj = new object();
foreach (var item in list)
  InvokeAsync(item, url, response => { lock(lockObj) newList.Add(response); });

Выше должно работать, я считаю; однако моя проблема в том, что я понятия не имею, как ждать, пока все ответы вернутся. Если я использую счетчик и жду в цикле, пока он не станет равным нулю, не останется никакого процессора для обработки обратных вызовов. Я полагаю, что то же самое с использованием какой-либо формы семафора. Есть ли неблокирующий способ подождать, пока я не верну все ответы? (Боюсь, что изменение сигнатуры метода также для обратного вызова переместит проблему только на один уровень вверх.)

[Edit] Вот очень близкий вопрос - Как вызвать асинхронную операцию как синхронизацию? - но мне нужно подождать нескольких асинхронных операций.

Ответы [ 2 ]

3 голосов
/ 12 ноября 2010

Для этого вы используете AutoResetEvent.

Попробуйте следующие две последние строки:

var waitEvent = new AutoResetEvent(false);

foreach (var item in list)
  InvokeAsync(item, url, response => { lock(lockObj) newList.Add(response); waitEvent.Set(); });

while (newList.Count < list.Count)
  waitEvent.WaitOne();

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

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

0 голосов
/ 12 ноября 2010

Согласно протоколу HTTP, клиент может открыть только 2 подключения к услуге.

...