I'm having some trouble getting my head around async/await. I'm helping with an existing code base that has the following code (simplified, for brevity):
List<BuyerContext> buyerContexts = GetBuyers();
var results = new List<Result>();
Parallel.ForEach(buyerContexts, buyerContext =>
{
//The following call creates a connection to a remote web server that
//can take up to 15 seconds to respond
var result = Bid(buyerContext);
if (result != null)
results.Add(result);
}
foreach (var result in results)
{
// do some work here that is predicated on the
// Parallel.ForEach having completed all of its calls
}
How can i convert this code to asynchronous code instead of parallel using async/await? I'm suffering from some pretty severe performance issues that I believe are a result of using a parallel approach to multiple network I/O operations.
I've tried several approaches myself but I'm getting warnings from Visual Studio that my code will execute synchronously or that I can't use await keywords outside of an async method so I'm sure I'm just missing something simple.
EDIT #1: I'm open to alternatives to async/await as well. That just seems to be the proper approach based on my reading so far.
EDIT #2: This application is a Windows Service. It calls out to several "buyers" to ask them to bid on a particular piece of data. I need ALL of the bids back before processing can continue.
The key to "making things async" is to start at the leaves. In this case, start in your network code (not shown), and change whatever synchronous call you have (e.g., WebClient.DownloadString
) to the corresponding asynchronous call (e.g., HttpClient.GetStringAsync
). Then await
that call.
Using await
will force the calling method to be async
, and change its return type from T
to Task<T>
. It is also a good idea at this point to add the Async
suffix so you're following the well-known convention. Then take all of that method's callers and change them to use await
as well, which will then require them to be async
, etc. Repeat until you have a BidAsync
method to use.
Then you should look at replacing your parallel loop; this is pretty easy to do with Task.WhenAll
:
List<BuyerContext> buyerContexts = GetBuyers();
var tasks = buyerContexts.Select(buyerContext => BidAsync(buyerContext));
var results = await Task.WhenAll(tasks);
foreach (var result in results)
{
...
}
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