I have an Async controller action method which calls 4 async methods on my Backend to return List from each. The List of objects is different for each method. ie List List etc.
I have this working as so:
BizProvider bp = new BizProvider();
List<biz.Customer> custReturn = await bp.GetCustomerAsync();
List<biz.Account> acctReturn = await bp.GetAccountAsync();
...plus 2 more
List<object> returnArr = new List<object>();
returnArr.Add(custReturn);
returnArr.Add(acctReturn); ...plus 2 more
return JsonConvert.SerializeObject(returnArr);
Should I use Task.WhenAll
because of multiple Tasks?
The example at the microsoft https://msdn.microsoft.com/en-us/library/hh194874%28v=vs.110%29.aspx
All the Tasks return List<int>
So I used and abstract class and had all my list object types inherit from this. and I changed the return type of my business object provider to return the List of abstract type so now I can do:
var tasks1 = new List<Task<List<Biz.AbstractClass>>>();
tasks1.Add(bp.GetCustomerAsAbstractAsync());
tasks1.Add(bp.GetAccountAsAbstractAsync());
...plus 2 more
I then call var continuation = Task.WhenAll(tasks1);
this executes then the next line it gets to the .Results
but then stops executing???
foreach (var result in continuation.Result)
^ stops here
further on I call
returnArrays.Add(result1);
return JsonConvert.SerializeObject(returnArrays);
but these never get hit...I don't know why.
Perhaps I don't need a WhenAll
, but then I am still curious what is going wrong.
perhaps I need an await on the specific functions, or invoke the Action somehow, as in the Microsoft link the functions are called inline.
Task.Run(async () => { x=x,etc...)
Edit 20150306 => adding more implementation details
CustMan cm = new CustMan();
List<object> returnArr = new List<object>();
var aTask = cm.GetCustomersAsync();
var bTask = cm.GetAccountsAsync();
await Task.WhenAll(aTask, bTask);
returnArr.Add(aTask.Result);//same for bTask <-- breakpoint never hits
return JsonConvert.SerializeObject(returnArr);
//also .js ajax return method never comes back.
//in CustMan()
public async Task<List<biz.Customer>> GetCustomersAsync() {
List<biz.Customer> custList = await (from contact in ObjectContextDb.GetData<da.ContactInfo>()//<--generic returns IQueryable
join customerContact in ObjectContextDb.GetData<da.CustomerContact>() on contact.Id equals customerContact.ContactInfoID
join customerOrg in ObjectContextDb.GetData<da.CustomerOrganisation>() on customerContact.OrgID equals customerOrg.Id
orderby contact.LastName
select new biz.Customer {
CustomerContactInfo = new biz.Contact() {
ID = contact.Id,
WorkPhone = contact.WorkPhone
},
CustomerOrg = new biz.CustomerOrganisation {
ID = facultyOrg.Id,
Name = facultyOrg.OrgName,
ClientID = (customerContact.ClientID.HasValue ? customerContact.ClientID.Value : 0)
}
}).ToListAsync<biz.Customer>();
return custList;// <-- Breakpoint hits here, the List has items
}
public async Task<List<biz.Account>> GetAccountsAsync()
{
var roles = (from acctType in ObjectContextDb.GetData<da.AccountInType>()
join r in ObjectContextDb.GetData<da.AccountType>() on acctType.AccountTypeID equals r.ID
select new
{
AccountId = acctType.AccountID,
Type = r.TypeName
}); //.ToList();
List<biz.Account> allContacts = await (from account in ObjectContextDb.GetData<da.Account>()
orderby account.Name
select new biz.Account()
{
Number = account.Id,
Name = account.Name,
Roles = (from r in roles where account.Id == r.AccountId select r.Type).ToList()
}).ToListAsync<biz.Account>();
return allContacts;// <-- Breakpoint hits here, the List has items
}
The method which calls the Manager Class methods without WhenAll
works!
CustMan cm = new CustMan();
List<object> returnArrays = new List<object>();
List<biz.Customer> custReturn = await cm.GetCustomersAsync();
List<biz.Account> acctReturn = await cm.GetAccountsAsync();
returnArrays.Add(custReturn);
returnArrays.Add(acctReturn);
return JsonConvert.SerializeObject(returnArrays);
No, you should not. Making everything async hurts reading, writing and understanding your code, even if only a little. It could also hurt the performance of your code, especially if you really made every single method (does that include properties?) async .
WhenAll() method in . NET Core. This will upload the first file, then the next file. There is no parallelism here, as the “async Task” does not automatically make something run in in parallel.
The main benefits of asynchronous programming using async / await include the following: Increase the performance and responsiveness of your application, particularly when you have long-running operations that do not require to block the execution.
You can use Task.WhenAll
without changing anything. Just store the tasks in a variable and add their results afterwards:
var aTask = GetAAsync();
var bTask = GetBAsync();
...
await Task.WhenAll(aTask, bTask);
returnArr.Add(aTask.Result);
returnArr.Add(bTask.Result);
In you case however, the async operations use Entity Framework which doesn't support multiple operations concurrently so you can't do that.
Call and await your operations one at a time:
returnArr.Add(await GetAAsync());
returnArr.Add(await GetBAsync());
...
It sounds like you're doing this:
var continuation = Task.WhenAll(tasks1);
foreach (var result in continuation.Result) { }
Which is probably deadlocking. WhenAll
returns a Task
too, so you'll need to await
that:
var results = await Task.WhenAll(tasks1);
foreach (var result in results) { }
Otherwise, building a List
of tasks and passing them into WhenAll
is a perfectly reasonable way to await multiple tasks concurrently.
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