Keerthi
Keerthi

Reputation: 135

async await vs TaskFactory.StartNew and WaitAll

I've got a NServiceBus host that goes and downloads a whole bunch of data once a message comes through about a particular users account. One data file is about 3Mb (myob - via a webservice call) and another is about 2Mb (restful endpoint, quite fast!). To avoid waiting around for long, I've wrapped the two download calls like this:

var myobBlock = Task.Factory.StartNew(() => myobService.GetDataForUser(accountId, datablockId, CurrencyFormat.IgnoreValidator));
var account = Task.Factory.StartNew(() => accountService.DownloadMetaAccount(accountId, securityContext));

Task.WaitAll(myobBlock, account);

var myobData = myobBlock.Result;
var accountData = account.Result;
//...Process AccountData Object using myobData object

I'm wondering what the benefits are for using the new async/await patterns are here compared to the TPL-esque method I've got above. Reading Stephen Clearys notes, it seems that the above would cause the thread to sit there waiting, where as Async/Await would continue and release the thread for other work.

How would you rewrite that within the context of Async/Await and would it be beneficial? We have lots of accounts to process but its once MSMQ message per account (end of FY reporting) or per-request (ad-hoc when a customer calls up and wants their report)

Upvotes: 2

Views: 774

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

The benefit of using async/await is that given a true async api (One which doesn't call sync methods over async using Task.Run and the likes, but does true async I/O work) you can avoid the allocation of any unnecessary Threads which simply waste resources only to wait on blocking I/O operations.

Lets imagine both your service methods exposed an async api, you could do the following instead of using two ThreadPool threads:

var myobBlock = myobService.GetDataForUserAsync(accountId, datablockId, CurrencyFormat.IgnoreValidator));

var account = accountService.DownloadMetaAccountAsync(accountId, securityContext));

// await till both async operations complete
await Task.WhenAll(myobBlock, account);

What will happen is that execution will yield back to the calling method until both tasks complete. When they do, continuation will resume via IOCP onto the assigned SynchronizationContext if needed.

Upvotes: 3

Related Questions