I need to make multiple asynchronous calls from inside a wcf service hosted in IIS (might be relevant, I don't know). The calls are to other services, but I make them by POSTing a string to the service URL. Calling them synchronously works, but I have more than a dozen calls, and they're completely independent, so I would like to speed them up by calling them asynchronously.
Now, I realize that I could simply use multiple threads for this - and it might be the easiest solution - but I thought I'd give async a try.
My code is similar to this:
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); });
The above should work, I believe; however, my problem is that I have no idea how to wait until all the responses are back. If I use a counter and wait in a loop until it becomes zero, there won't be any CPU left to handle the callbacks. Same with using some form of semaphore, I believe. Is there a non-blocking way to wait until I got back all the responses? (Changing the method signature to also take a callback will only move the problem one level up, I'm afraid.)
[Edit] Here's a very close question - How to invoke async operation as sync? - but I need to wait on multiple async operations.
You use an AutoResetEvent
for this.
Try the following for your last two lines:
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();
All items should be completed when newList
contains as many items as list
. When a new item comes in, you add it to newList
. Then, you signal the waitEvent
that "something" happened to newList
.
In the main thread, you simply wait until you have enough items in newList
and you wait for this by waiting on changes to newList
, which waitEvent
informs you of.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With