programing

Httpclient 이 인스턴스가 이미 하나 이상의 요청을 시작했습니다.속성은 첫 번째 요청을 보내기 전에만 수정할 수 있습니다.

powerit 2023. 8. 1. 20:51
반응형

Httpclient 이 인스턴스가 이미 하나 이상의 요청을 시작했습니다.속성은 첫 번째 요청을 보내기 전에만 수정할 수 있습니다.

에서 응용프로그램을 만들고 있습니다.NetCore 2.1과 저는 웹 요청에 http client를 사용하고 있습니다.문제는 시간을 절약하기 위해 병렬 통화를 해야 한다는 것이고, 그 때문에 작업을 사용하고 있다는 것입니다.All() 메서드를 사용하지만 이 메서드를 누르면 "이 인스턴스가 이미 하나 이상의 요청을 시작했습니다.속성은 첫 번째 요청을 보내기 전에만 수정할 수 있습니다." 이전에는 RestSharp를 사용했고 모든 것이 괜찮았지만 httpclient를 사용하고 싶습니다.코드는 다음과 같습니다.

public async Task<User> AddUser(string email)
{
    var url = "user/";
    _client.BaseAddress = new Uri("https://myWeb.com/");
    _client.DefaultRequestHeaders.Accept.Clear();
    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants."application/json"));
    _client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    var json = new {email = email }
    var response = await _client.PostAsJsonAsync(url,json);
    if (response .IsSuccessStatusCode)
    { ....

생성자는 다음과 같습니다.

private readonly HttpClient _httpClient;

public UserRepository(HttpClient httpClient)
{         
    _httpClient = httpClient;
}

메서드 호출:

var user1 = AddUser("user@user.com");
var user2 = AddUser("test@test.com");

await Task.WhenAll(user1, user2);

시작 구성은 다음과 같습니다.

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

그럼 내가 뭘 잘못하고 있는 거지?AddSingleton을 AddTransient()로 변경해야 합니까, 아니면 다른 문제가 있습니까?_client를 사용해야 하는 질문이 하나 더 있습니다.제가 팔로우한 튜토리얼이 폐기 방법을 사용하지 않았기 때문에 응답 후 폐기()는 혼란스럽습니다.

HttpClient.DefaultRequestHeaders(및BaseAddress요청하기 전에 한 번만 설정해야 합니다.HttpClient한 번 사용한 후 수정하지 않는 경우에만 싱글톤으로 사용하는 것이 안전합니다.

설정보다는DefaultRequestHeaders각각의 헤더를 설정합니다.HttpRequestMessage보내는 중입니다.

var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("{...}", Encoding.UTF8, "application/json");
var response = await _client.SendAsync(request, CancellationToken.None);

교체하다"{...}"당신의 JSON과 함께.

아마 내 2센트가 누군가를 도울 것입니다.

응용 프로그램을 디버깅할 때 페이지를 새로 고칠 때 이 문제가 발생했습니다.

싱글톤을 사용했는데 매번 새로고침할 때마다 기본 주소를 설정하려고 했습니다.그래서 그냥 기본 주소가 이미 정해졌는지 확인하기 위해 수표로 포장했습니다.

문제는 baseAddress가 이미 설정되어 있음에도 불구하고 설정하려고 한다는 것입니다.httpClient에서는 이 작업을 수행할 수 없습니다.

if (_httpClient.BaseAddress == null)
{
    _httpClient.BaseAddress = new Uri(baseAddress);
}

이 문제는 httpclient의 동일한 인스턴스에 대해 BaseAddress 및 헤더를 재설정하여 발생합니다.

나는 노력했다.

if (_httpClient.BaseAddress == null) 

하지만 저는 이것을 좋아하지 않습니다.

제 생각에 더 나은 해결책은 httpclient Factory를 사용하는 것입니다.이 작업은 종료되고 사용 후 httpclient의 인스턴스를 가비지 수집합니다.

private readonly IHttpClientFactory _httpClientFactory;
public Foo (IHttpClientFactory httpClientFactory) 
{
_httpClientFactory = httpClientFactory;
}
public  httpresponse Bar ()
{
_httpClient = _httpClientFactory.CreateClient(command.ClientId);

using var response = await _httpclient.PostAsync(uri,content);
return response;
// here as there is no more reference to the _httpclient, the garbage collector will clean 
// up the _httpclient and release that instance. Next time the method is called a new 
// instance of the _httpclient is created
}

클라이언트가 아닌 메시지에서 요청 URL 및 헤더를 추가할 때 잘 작동합니다.그래서 할당하지 않는 것이 좋습니다.BaseAddress아니면 머리글이DefaultRequestHeaders많은 요청에 사용할 수 있습니다.

HttpRequestMessage msg = new HttpRequestMessage {
    Method = HttpMethod.Put,
    RequestUri = new Uri(url),
    Headers = httpRequestHeaders;
};

httpClient.SendAsync(msg);

이 질문은 시간이 좀 걸리지만, 저는 단지 고객에게 전화를 걸려고 했을 뿐입니다.Parallel.ForEachAsync 루우프

Mali Tbt의 답변을 기반으로 해결되었습니다.

주사를 놓았습니다.IHttpClientFactory생성자에서 각 반복에서 클라이언트 인스턴스를 만드는 데 사용했습니다.

OP 사례 적용:

private readonly IHttpClientFactory _clientFactory;

// Constructor
public UserRepository(IHttpClientFactory httpClientFactory)
  {         
      _clientFactory = httpClientFactory;
  }

// calling method
public async Task<User> AddUser(string email)
{
    var url = "user/";
    var client = _clientFactory.CreateClient("UserRepository");

    client.BaseAddress = new Uri("https://myWeb.com/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants."application/json"));
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    var json = new {email = email }
    var response = await client.PostAsJsonAsync(url,json);
    if (response .IsSuccessStatusCode)
    { ....

언급URL : https://stackoverflow.com/questions/51478525/httpclient-this-instance-has-already-started-one-or-more-requests-properties-ca

반응형