Httpclient 这个实例已经开始了一个或多个请求。只能在发送第一个请求之前修改属性
Httpclient This instance has already started one or more requests. Properties can only be modified before sending the first request
我正在 .Net Core 2.1 中创建一个应用程序,我正在使用 http 客户端进行 Web 请求。问题是我必须发送并行调用以节省时间,为此我正在使用 Task.WhenAll() 方法但是当我点击此方法时出现错误 "This instance has already started one or more requests. Properties can only be modified before sending the first request" 之前我使用的是 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>();
那我做错了什么?我需要用 AddTransient() 更改 AddSingleton 还是有任何其他问题。还有一个问题我需要在回复后使用 _client.Dispose() 因为我遵循的教程没有使用 dispose 方法所以我对此有点困惑。
HttpClient.DefaultRequestHeaders
(和BaseAddress
)应该只设置一次,在你提出任何请求之前。 HttpClient
只有在使用后不进行修改的情况下才能安全地用作单例。
不是设置 DefaultRequestHeaders
,而是在您发送的每个 HttpRequestMessage
上设置 headers。
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。
也许我的两分钱能帮到别人。
我 运行 在调试应用程序时刷新页面时遇到了这个问题。
我使用的是单例,但每次刷新时,它都会尝试设置基地址。所以我只是把它包裹在一个检查中,看看是否已经设置了基地址。
我遇到的问题是,它试图设置 baseAddress,即使它已经设置好了。您不能使用 httpClient 执行此操作。
if (_httpClient.BaseAddress == null)
{
_httpClient.BaseAddress = new Uri(baseAddress);
}
此问题是由为同一 httpclient 实例重置 BaseAddress 和 headers 引起的。
我试过了
if (_httpClient.BaseAddress == null)
不过我不喜欢这个
在我看来,更好的解决方案是使用 httpclientFactory。这将在使用后终止并垃圾收集 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 和 header 时效果很好,而不是在客户端。所以最好不要分配给 BaseAddress
或 header DefaultRequestHeaders
如果您将它们用于许多请求。
HttpRequestMessage msg = new HttpRequestMessage {
Method = HttpMethod.Put,
RequestUri = new Uri(url),
Headers = httpRequestHeaders;
};
httpClient.SendAsync(msg);
我正在 .Net Core 2.1 中创建一个应用程序,我正在使用 http 客户端进行 Web 请求。问题是我必须发送并行调用以节省时间,为此我正在使用 Task.WhenAll() 方法但是当我点击此方法时出现错误 "This instance has already started one or more requests. Properties can only be modified before sending the first request" 之前我使用的是 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>();
那我做错了什么?我需要用 AddTransient() 更改 AddSingleton 还是有任何其他问题。还有一个问题我需要在回复后使用 _client.Dispose() 因为我遵循的教程没有使用 dispose 方法所以我对此有点困惑。
HttpClient.DefaultRequestHeaders
(和BaseAddress
)应该只设置一次,在你提出任何请求之前。 HttpClient
只有在使用后不进行修改的情况下才能安全地用作单例。
不是设置 DefaultRequestHeaders
,而是在您发送的每个 HttpRequestMessage
上设置 headers。
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。
也许我的两分钱能帮到别人。
我 运行 在调试应用程序时刷新页面时遇到了这个问题。
我使用的是单例,但每次刷新时,它都会尝试设置基地址。所以我只是把它包裹在一个检查中,看看是否已经设置了基地址。
我遇到的问题是,它试图设置 baseAddress,即使它已经设置好了。您不能使用 httpClient 执行此操作。
if (_httpClient.BaseAddress == null)
{
_httpClient.BaseAddress = new Uri(baseAddress);
}
此问题是由为同一 httpclient 实例重置 BaseAddress 和 headers 引起的。
我试过了
if (_httpClient.BaseAddress == null)
不过我不喜欢这个
在我看来,更好的解决方案是使用 httpclientFactory。这将在使用后终止并垃圾收集 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 和 header 时效果很好,而不是在客户端。所以最好不要分配给 BaseAddress
或 header DefaultRequestHeaders
如果您将它们用于许多请求。
HttpRequestMessage msg = new HttpRequestMessage {
Method = HttpMethod.Put,
RequestUri = new Uri(url),
Headers = httpRequestHeaders;
};
httpClient.SendAsync(msg);