C# VssHttpMessageHandler和HttpMessageHandler池

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

我目前正在使用Azure Devops客户端库进行C#。 出于许多原因(如避免端口耗尽或可测试性),我希望使用dotnetcore提供的IHttpMessageHandlerFactory为我的VSS连接提供处理程序。 目前,我使用的是:

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);