2015-03-05 2 views
3

У меня есть метод действий контроллера Async, который вызывает 4 метода async для моего Backend для возврата списка из каждого. Список объектов для каждого метода отличается. т.е. список Список т.д.Несколько методов Async, лучше всего использовать WhenAll с разными типами возвращаемых данных

я это работает, как так:

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); 

Должен ли я использовать Task.WhenAll из нескольких задач?

Пример на майкрософт https://msdn.microsoft.com/en-us/library/hh194874%28v=vs.110%29.aspx

Все эти задачи возвращают List<int>

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

var tasks1 = new List<Task<List<Biz.AbstractClass>>>(); 
tasks1.Add(bp.GetCustomerAsAbstractAsync()); 
tasks1.Add(bp.GetAccountAsAbstractAsync()); 
...plus 2 more 

Я тогда называть вар продолжение = Task.WhenAll (tasks1);

это выполняет следующую строку, которую он получает до .Results, но затем прекращает выполнение ???

foreach (var result in continuation.Result) 
            ^stops here 

далее я называю

returnArrays.Add(result1); 
return JsonConvert.SerializeObject(returnArrays); 

, но они никогда не попасть ... Я не знаю, почему. Возможно, мне не нужен WhenAll, но тогда мне все еще интересно, что происходит не так. Возможно, мне нужно ждать определенных функций или вызвать действие так или иначе, как в ссылке Microsoft, функции называются встроенными.

Task.Run(async() => { x=x,etc...) 

Редактировать 20150306 => Добавление большего количества деталей реализации

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 
} 

Метод, который вызывает методы класса менеджера без WhenAll работ!

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); 
+0

Вы можете вызвать '.GetAllFacultyAsync()' и '.GetAllContactsWithRolesAsync()' и ждать их позже. Это вызовет все асинхронные запросы, но ждет их позже, сохраняя их строго типизированными. – Caramiriel

ответ

5

Вы можете использовать Task.WhenAll, не изменяя ничего.Просто хранить задания в переменной и добавить их результаты впоследствии:

var aTask = GetAAsync(); 
var bTask = GetBAsync(); 
... 
await Task.WhenAll(aTask, bTask); 
returnArr.Add(aTask.Result); 
returnArr.Add(bTask.Result); 

В вас случае, однако, операции используют асинхронные Entity Framework, который doesn't support multiple operations concurrently так что вы не можете сделать это.

вызов и ждут ваших операций по одному:

returnArr.Add(await GetAAsync()); 
returnArr.Add(await GetBAsync()); 
... 
+0

Я пробовал это, но если бы я поставил точку останова после ожидания, она никогда не попадет, а вызов ajax, который попадает в метод действия который вызывает это, никогда не возвращается. – matthewbaskey

+0

@magister, тогда ваши задачи никогда не завершатся. Покажите код для них. – i3arnon

+0

var aTask = cm.GetCustomersAsync(); var bTask = cm.GetAccountsAsync(); // выше CustMan cm = new CustMan(); Список returnArr = новый Список (); ожидание Task.WhenAll (aTask, bTask); returnArr.Add (aTask.Result); // тот же для bTask <- точка останова никогда не обращается к возврату JsonConvert.SerializeObject (returnArr); // также .js ajax return никогда не приходит – matthewbaskey

1

Это звучит, как вы делаете это:

var continuation = Task.WhenAll(tasks1); 
foreach (var result in continuation.Result) { } 

который, вероятно, deadlocking. WhenAll возвращает Task тоже, так что вам нужно await что:

var results = await Task.WhenAll(tasks1); 
foreach (var result in results) { } 

В противном случае, строительство List задач и передавая их в WhenAll является вполне разумным способом ждать несколько задач одновременно.

+0

oh jez, я пропустил это – matthewbaskey

+0

Знаете ли вы, если бы я поставил точку останова после foreach .... будет ли она ударить? Я добираюсь до этого момента, никаких исключений, но затем меня выталкивают в Acquire_RequestState в global.asax.cs – matthewbaskey

Смежные вопросы