Как выполнить операцию postasync внутри цикла в C#

#c# #.net-core #hangfire

Вопрос:

У меня есть работа с зависанием, построенная в C# .netcore. Эта работа заключается в выполнении вызова postasync внутри forloop. После первого вызова api он выдает ошибку ниже.

Этот экземпляр уже запустил один или несколько запросов. Свойства могут быть изменены только перед отправкой первого запроса

Как эффективно выполнять вызов синхронно в цикле? Вызов должен быть синхронным.

 class myclass
{

  public void process(){
  
   _httpClient = new HttpClient();
   
   foreach(var item in list){
   _httpClient.BaseAddress = baseUri;
            _httpClient.DefaultRequestHeaders.Clear();
            _httpClient.DefaultRequestHeaders.ConnectionClose = true
    var res=  _httpClient.PostAsync(url,body);
    var result= res.content.readasstringasync().Resu<
    saveResultInDB(result);
   }
  }
 

Комментарии:

1. Опубликуйте фактический, полный текст исключения и фактический, выполняемый код . Опубликуйте полный результат Exception.ToString() , а не только сообщение. res.content.readasstringasync().Resu< даже не будет компилироваться, и если бы это было так, блокировка асинхронной операции-плохая идея. Используйте await вместо этого

2. Вы изменяетесь BaseAddress или находитесь DefaltRequestHeaders в цикле?

3. @PanagiotisKanavos Да, я изменил фрагмент кода.

4. Вам нужно await PostAsync позвонить (и ReadAsStringAsync тому тоже)

5. Код не будет компилироваться, в нем есть ошибки параллелизма, но непосредственная проблема заключается в том, что вы изменяете адрес и заголовки по умолчанию. Не делай этого. Они предназначены для установки только один раз. HttpClient предназначен для повторного использования, поэтому эти свойства действительно являются значениями по умолчанию, используемыми всеми вызовами. ` _httpClient = новый HttpClient();` также является ошибкой, которая приведет к исчерпанию сокета по мере создания все большего числа экземпляров HttpClient

Ответ №1:

HttpClient является потокобезопасным и предназначен для повторного использования. Изменение BaseAddress и DefaultRequestHeaders модификация значений по умолчанию, используемых всеми запросами, включая текущие. Изменение их внутри цикла только вызывает проблемы.

Методы HttpClient являются асинхронными. Вместо того, чтобы блокировать каждый из них, гораздо проще и чище написать правильный асинхронный метод, а затем, если и только если в этом есть реальная необходимость, вызвать его блокирующим способом.

Если предположить, что базовый URL-адрес и заголовки не изменяются, код может измениться на :

 
HttpClient _httpClient;

public MyClass()
{
    _httpClient=new HttpClient();
    _httpClient.DefaultHeaders......;
}

public void Process()=>ProcessAsync().Wait();

public async Task ProcessAsync(List<Item> items)
{ 
   foreach(var item in items)
   {    
        var absoluteUrl=CalculateUrl(item);
        var res=  await _httpClient.PostAsync(absoluteUrl,item.Body);
        var result= await res.Content.ReadAsStringAsync();
        saveResultInDB(result);
   }
}
 

Комментарии:

1. Спасибо за подробное объяснение. если мне нужно установить базовую авторизацию и учетные данные также изменяются на основе URL-адреса, как это обработать?