2015-06-01 2 views
0

Неверно использовать asyc для ожидания в цикле foreach? Я получаю WebException, запрос был отменен.Использование asyn ждет в цикле foreach

Ниже приводится только схема кода, над которым я работаю. Пожалуйста, дайте мне знать, если это не ясно.

using (var client = new HttpClient()) 
{ 
    client.BaseAddress = new Uri("https://xxx.xxx.com/"); 
    client.DefaultRequestHeaders.Accept.Clear(); 
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

    try 
    { 
     var response = await client.PostAsJsonAsync("customers/xxxx/xxx/documents", requestMessage); 

     response.EnsureSuccessStatusCode(); 
     var returnValue = response.Content.ReadAsAsync<ResponseMessage>(); 

     var hasDocuments = returnValue.Result.SearchResults.Any(); 

     if (hasDocuments) 
     { 
      // HTTP GET 
      client.DefaultRequestHeaders.Accept.Clear(); 
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); 

      returnValue.Result.SearchResults.ForEach(async d => 
      { 
       response = await client.GetAsync(d.Self + ".pdf"); 
      }); 
     } 
    } 
    catch (Exception ex) 
    { 
     throw; 
    } 
} 

ответ

7

Вы не используете асинхр/ждут в foreach цикле, вы используете асинхр/ждут с List<T>.ForEach(Action<T>). Поскольку ForEach принимает только Action<T> (тип возврата void), ваш ForEach(async d => { ... } обрабатывается как функция async void, потому что это единственный способ передать его как Action<T>. Это заставляет ForEach не дожидаться завершения предыдущего элемента до перехода к следующему элементу, и это вызывает вашу ошибку.

Используйте обычный foreach вместо метода , и он должен работать нормально.

if (hasDocuments) 
    { 
     // HTTP GET 
     client.DefaultRequestHeaders.Accept.Clear(); 
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); 

     foreach (var d in returnValue.Result.SearchResults) 
     { 
      response = await client.GetAsync(d.Self + ".pdf"); 
     }; 
    } 

Единственный раз, когда вам разрешено использовать async d => ..., когда функция, которую вы передаете, чтобы берет в Func<T,Task> (См Task.Run в качестве примера).

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