2015-02-23 5 views
0

У меня есть проблема с асинхронным программированием.Асинхронный, два ожидаемых метода. Только один возвращает

Если вы посмотрите на этот пример:

public async void SaveUsersThings(List<User> Users) 
{      
    await SaveUsersCars(Users); 
    await SaveUsersHouses(Users);   
} 

Так я ожидаю SaveUsersThings выполнить следующие два метода:

public async Task SaveUsersCars(List<User> Users) 
{ 
    var listofCars = new List<Car>(); 
    foreach (var item in Users) 
    { 
     var cars = await _sqlrepo.GetAllCars(item.UserId); 
     foreach (var car in cars) 
     { 
      listofCars.Add(car); 
     } 
    } 

    _sqlrepo.SaveListOfCars(listofCars); 
} 

И тогда это (идентично, как указано выше для OBJ исключением)

public async Task SaveUsersHouses(List<User> Users) 
{ 
    var listofHouses = new List<House>(); 
    foreach (var item in Users) 
    { 
     var houses = await _sqlrepo.GetAllHouses(item.UserId); 
     foreach (var house in houses) 
     { 
      listofHouses.Add(house); 
     } 
    } 
    _sqlrepo.SaveListOfHouses(listofHouses); 
} 

Проблема в том, что только первый метод завершает то, что он (чтобы сохранить некоторые вещи в db). Думаю, это связано с тем, что я не совсем понимаю этот вид программирования. Может кто-нибудь объяснить, как я могу заставить оба метода «работать»?

Спасибо

+1

Вы пробовали отлаживать? Мы не можем помочь с предоставленной информацией. Может быть, ошибка с реализацией '_sqlrepo.SaveListOfHouses'? Отлаживайте свой код и находите, где это происходит. –

+1

Возможно, первое бросает исключение. Ваш код будет выполнять две задачи в последовательности. – Jacob

+0

Что ... на земле ... вы делаете в этом методе? Надеюсь, вы отредактировали код, в котором вы делаете * что-то, в список объектов после их получения и перед тем, как записать их в базу данных. Потому что, черт возьми, сын. – Will

ответ

4
public async void SaveUsersThings(List<User> Users) 

Как вы можете знать, если есть ошибка? async void эффективно игнорирует любые ошибки. (Я подозреваю, что команда C# действительно не хотела поддерживать async void вообще, но для обратной совместимости с некоторыми существующими парадигмами. Что-то о обработчиках событий, я не знаю.) В основном void предотвращает использование любого кода потребления ожидая результата или рассматривая этот результат. Таким образом, вполне может быть AggregateException, которому просто некуда идти.

async должно быть "async all the way down". Сделать метод верхнего уровня awaitable:

public async Task SaveUsersThings(List<User> Users) 

Этот путь любой вызывающую SaveUsersThings() может ждать его и изучить результат. Это может не гарантировать, что «оба метода будут работать», но он хотя бы разоблачает причину , что что-то не работает. Вместо угадывания.

+0

Методы 'async void' будут обрабатывать процесс. Не так ли? –

+0

@SriramSakthivel: Я не уверен, что вы просите. Насколько я знаю, 'async void' просто не является ожидаемым или экзаменуемым, потому что он не возвращает' Task'. Таким образом, это эффективно «огонь и забыть». И проблема с «пожаром и забытью» становится понятной, когда есть ошибка, так как код по дизайну не может сообщить об этой ошибке. 'async void' * can *, но любой асинхронный код в нем должен быть обработан * очень тщательно * и с сильным пониманием контекстов синхронизации. – David

+2

@SriramSakthivel Нет, незаметные исключения задачи больше не будут обрабатывать процесс, [это изменение на .net в 4.5] (http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/ задача-обработка исключений в внутрисетевом-4-5.aspx) для того, чтобы получить старое поведение обратно вам нужно поставить '<конфигурация> ' в вашем app.config. –