【发布时间】:2020-02-12 13:26:26
【问题描述】:
此服务从两个位置获取令牌并将令牌作为标头附加到每个 HTTP 请求中。我不知道为什么,但我收到了这个错误。我正在处理异步,但这个任务仍然被取消。
public class TokenService : DelegatingHandler, IHostedService
{
public IConfiguration Configuration { get; }
private Timer _timer;
public IHttpClientFactory _clientFactory;
protected HttpClient _client_SB;
protected HttpClient _client_Opsman_SB;
private readonly IServiceScopeFactory _scopeFactory;
string connectionString = "";
public TokenService(IConfiguration configuration, IHttpClientFactory clientFactory, IServiceScopeFactory scopeFactory)
{
Configuration = configuration;
_clientFactory = clientFactory;
_scopeFactory = scopeFactory;
connectionString = Configuration.GetConnectionString("DefaultConnection");
_client_SB = _clientFactory.CreateClient("TestEnv");
_client_Opsman_SB = _clientFactory.CreateClient("OpsmanTestEnv");
}
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(GetAccessToken, null, 0, 3300000);
_timer = new Timer(GetAccessTokenOpsMan, null, 0, 3300000);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
//Timer does not have a stop.
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public async Task<Token> GetToken(Uri authenticationUrl, Dictionary<string, string> authenticationCredentials)
{
HttpClient client = new HttpClient();
FormUrlEncodedContent content = new FormUrlEncodedContent(authenticationCredentials);
HttpResponseMessage response = await client.PostAsync(authenticationUrl, content);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
string message = String.Format("POST failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
string responseString = await response.Content.ReadAsStringAsync();
Token token = JsonConvert.DeserializeObject<Token>(responseString);
return token;
}
private void GetAccessToken(object state)
{
Dictionary<string, string> authenticationCredentials_sb = Configuration.GetSection("TestEnvironment:Credentials").GetChildren().Select(x => new KeyValuePair<string, string>(x.Key, x.Value)).ToDictionary(x => x.Key, x => x.Value);
Token token_sb = GetToken(new Uri(Configuration["TestEnvironment:URL"]), authenticationCredentials_sb).Result;
_client_SB.DefaultRequestHeaders.Add("Authorization", $"Bearer {token_sb.AccessToken}");
}
private void GetAccessTokenOpsMan(object state)
{
Dictionary<string, string> authenticationCredentials_opsman_sb = Configuration.GetSection("OpsManTestEnvironment:Credentials").GetChildren().Select(x => new KeyValuePair<string, string>(x.Key, x.Value)).ToDictionary(x => x.Key, x => x.Value);
Token opsman_token_sb = GetToken(new Uri(Configuration["OpsManTestEnvironment:URL"]), authenticationCredentials_opsman_sb).Result;
_client_Opsman_SB.DefaultRequestHeaders.Add("Authorization", $"Bearer {opsman_token_sb.AccessToken}");
}
}
未处理的异常:System.AggregateException:一个或多个错误 发生了。 (一个任务被取消了。)---> System.Threading.Tasks.TaskCanceledException:任务被取消。 --- 内部异常堆栈跟踪结束 --- 在 System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)在 ProjectEcho.Services.TestService.GetAccessTokenOpsMan(Object state) in c:\agent_Work09\73\s\Services\TestService.cs:第 73 行 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext、ContextCallback 回调、对象状态) --- 从之前抛出异常的位置结束堆栈跟踪 --- 在 System.Threading.TimerQueueTimer.CallCallback() 处 System.Threading.TimerQueueTimer.Fire() 在 System.Threading.TimerQueue.FireNextTimers() }
【问题讨论】:
-
这几乎可以肯定是您的 HTTP 调用超时
-
我同意@KevinGosse 的观点。 Here 是我之前在类似问题上提供的答案。
-
所以增加超时可能是解决方案?
-
如果您使用
HttpClient类型的变量,请尝试执行httpClient.Timeout = new TimeSpan(0, asyncTimeoutInMins, 0);之类的操作,其中 asyncTimeoutInMins 是您希望返回令牌的某个值。实际上,请查看 TimeSpan 的其他构造函数,因为您不应该等待几分钟才能获得令牌。将其设置为某个值以至少测试这是否可以解决您的问题并从那里开始。 -
@MrMoose 这不是代码问题,事实证明它是网络问题它调用的 API 托管在与应用程序相同的基础上,所以它有点循环
标签: c# multithreading asp.net-core .net-core async-await