C# VssHttpMessageHandler和HttpMessageHandler池
我目前正在使用Azure Devops客户端库进行C#。 出于许多原因(如避免端口耗尽或可测试性),我希望使用dotnetcore提供的IHttpMessageHandlerFactory为我的VSS连接提供处理程序。 目前,我使用的是:C# VssHttpMessageHandler和HttpMessageHandler池,c#,.net-core,azure-devops,C#,.net Core,Azure Devops,我目前正在使用Azure Devops客户端库进行C#。 出于许多原因(如避免端口耗尽或可测试性),我希望使用dotnetcore提供的IHttpMessageHandlerFactory为我的VSS连接提供处理程序。 目前,我使用的是: var vssHttpMessageHandler = new VssHttpMessageHandler(new VssBasicCredential(string.Empty, options.Pat), VssClientHttpRequestSetti
var vssHttpMessageHandler = new VssHttpMessageHandler(new VssBasicCredential(string.Empty, options.Pat), VssClientHttpRequestSettings.Default.Clone(), _httpMessageHandlerFactory.CreateHandler(HttpClientName));
但是,这并不总是与重用处理程序时一样,会引发异常:
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw中处理的System.InvalidOperationException:
位于System.Net.Http.SocketsHttpHandler.CheckDisposedOrStarted(System.Net.Http,版本=4.2.2.0,区域性=neutral,PublicKeyToken=b03f5f7f11d50a3a)
位于Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.ApplySettings(Microsoft.VisualStudio.Services.Common,版本=16.0.0.0,区域性=中性,PublicKeyToken=b03f5f7f11d50a3a)
事实上,在构造VssHttpMessageHandler时,会将新设置应用于HttpMessageHandler,但是,此设置不支持在其使用开始后进行修改(其所有属性在设置时调用CheckDisposedOrStarted)
我能做些什么来实现我想做的事情
编辑:这是我的代码的复制
var azureDevopsUri = "https://dev.azure.com/mycollection";
var pat = "mypathere";
var services = new ServiceCollection();
services.AddHttpClient();
services.AddTransient(s =>
{
var handlerFactory = s.GetRequiredService<IHttpMessageHandlerFactory>();
var vssHandler = new VssHttpMessageHandler(
new VssBasicCredential(string.Empty, pat),
VssClientHttpRequestSettings.Default.Clone(),
handlerFactory.CreateHandler());
return new VssConnection(
new Uri(azureDevopsUri),
vssHandler,
new DelegatingHandler[] { });
});
var provider = services.BuildServiceProvider();
using(var scope = provider.CreateScope())
{
var connection = scope.ServiceProvider.GetRequiredService<VssConnection>();
var client = await connection.GetClientAsync<ProjectCollectionHttpClient>();
await client.GetProjectCollections();
}
using (var scope = provider.CreateScope())
{
var connection = scope.ServiceProvider.GetRequiredService<VssConnection>(); // <-- Exception thrown here
var client = await connection.GetClientAsync<ProjectCollectionHttpClient>();
await client.GetProjectCollections();
}
var azureDevopsUri=”https://dev.azure.com/mycollection";
var pat=“mypathere”;
var services=newservicecolection();
services.AddHttpClient();
services.AddTransient(s=>
{
var handlerFactory=s.GetRequiredService();
var vssHandler=新的VssHttpMessageHandler(
新VssBasicCredential(string.Empty,pat),
VssClientHttpRequestSettings.Default.Clone(),
handlerFactory.CreateHandler());
返回新的VssConnection(
新Uri(azureDevopsUri),
斯尚德勒,
新的委托人[]{});
});
var provider=services.BuildServiceProvider();
使用(var scope=provider.CreateScope())
{
var connection=scope.ServiceProvider.GetRequiredService();
var client=await connection.GetClientAsync();
等待client.GetProjectCollections();
}
使用(var scope=provider.CreateScope())
{
var connection=scope.ServiceProvider.GetRequiredService();//我使用VssHttpMessageHandler
进行了测试,但无法重现此问题
我想分享C#样本:
您可以参考答案中的示例。由于我无法根据您的代码重现此问题,请您共享更多示例代码和重现此问题的步骤好吗?另一方面,您可以直接将参数分配给vssconnection以进行连接。我已使用repro更新了消息。问题是在重用HttpMessageHandler提供时池中的ded.Hi@Nathanel Marchand。谢谢你的信息。我可以复制这个问题。根据我的测试,如果我删除handlerFactory.CreateHandler()
,它将成功构建。请尝试并检查它是否可以进行一些更改。是的,我知道我可以让sdk创建处理程序,但这可能会导致套接字耗尽。这就是为什么我希望使用aspnetcore/dotnetcore带来的池化改进(请参阅)
This instance has already started one or more requests. Properties can only be modified before sending the first request.
at System.Net.Http.SocketsHttpHandler.CheckDisposedOrStarted()
at System.Net.Http.HttpClientHandler.set_AllowAutoRedirect(Boolean value)
at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.ApplySettings(HttpMessageHandler handler, ICredentials defaultCredentials, VssHttpRequestSettings settings)
at UserQuery.<>c__DisplayClass4_0.<Main>b__0(IServiceProvider s), line 9
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at UserQuery.Main(), line 31
var azureDevopsUri = "https://dev.azure.com/org";
var pat = "PAT";
var services = new ServiceCollection();
services.AddHttpClient();
services.AddTransient(s =>
{
var handlerFactory = s.GetRequiredService<IHttpMessageHandlerFactory>();
var vssHandler = new VssHttpMessageHandler(
new VssBasicCredential(string.Empty, pat),
VssClientHttpRequestSettings.Default.Clone());
return new VssConnection(
new Uri(azureDevopsUri),
vssHandler,
new DelegatingHandler[] { });
});
var provider = services.BuildServiceProvider();
using (var scope = provider.CreateScope())
{
var connection = scope.ServiceProvider.GetRequiredService<VssConnection>();
var client = await connection.GetClientAsync<ProjectCollectionHttpClient>();
await client.GetProjectCollections();
}
using (var scope = provider.CreateScope())
{
var connection = scope.ServiceProvider.GetRequiredService<VssConnection>(); // <-- Exception thrown here
var client = await connection.GetClientAsync<ProjectCollectionHttpClient>();
await client.GetProjectCollections();
}
public VssHttpMessageHandler(VssCredentials credentials, VssHttpRequestSettings settings, HttpMessageHandler innerHandler);