.NET Core 6下C#同步调用交易API及定时器实现方案问询
同步HTTP调用优化方案
针对交易所禁止异步API调用的要求,你可以从以下几个方面优化同步HTTP调用实现:
复用HttpClient实例
.NET Core中HttpClient是线程安全的,频繁创建实例会导致套接字资源耗尽。通过IHttpClientFactory注册复用的客户端实例:// Program.cs 中注册 builder.Services.AddHttpClient("ExchangeWcfApi", client => { client.BaseAddress = new Uri("https://你的交易所API域名/wcf端点"); client.Timeout = TimeSpan.FromSeconds(30); // 设置合理超时,避免长时间阻塞 });后续通过依赖注入
IHttpClientFactory创建客户端,确保实例复用。严格同步的请求与响应处理
使用HttpClient.Send方法发起同步请求,同时避免使用任何异步读取响应的方法(如ReadAsStringAsync),改用同步流读取:var client = _httpClientFactory.CreateClient("ExchangeWcfApi"); var request = new HttpRequestMessage(HttpMethod.Post, "/目标接口"); request.Content = new StringContent("请求Payload", Encoding.UTF8, "application/xml"); // WCF常用XML格式 // 同步发送请求 var response = client.Send(request); response.EnsureSuccessStatusCode(); // 自动抛出HTTP错误状态码异常 // 同步读取响应内容 using var responseStream = response.Content.ReadAsStream(); using var streamReader = new StreamReader(responseStream); var responseContent = streamReader.ReadToEnd();同步重试机制
针对交易所API可能出现的临时故障,用Polly实现同步重试策略,避免频繁失败触发风控:// 定义重试策略:针对HTTP异常、5xx错误、429限流错误重试3次,指数退避 var retryPolicy = Policy .Handle<HttpRequestException>() .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode && (r.StatusCode >= HttpStatusCode.InternalServerError || r.StatusCode == HttpStatusCode.TooManyRequests)) .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // 执行带重试的同步请求 var response = retryPolicy.Execute(() => client.Send(request));
基于时间戳的轮询逻辑设计
针对每日多次定时调用的需求,推荐使用.NET Core的BackgroundService实现后台任务调度,避免System.Threading.Timer的线程池异常风险:
独立后台服务实现
创建继承自BackgroundService的轮询服务,内置时间计算与任务调度逻辑:public class ExchangeScheduledPollingService : BackgroundService { private readonly IHttpClientFactory _httpClientFactory; // 定义每日需要调用的时间点(24小时制) private readonly List<TimeSpan> _dailySchedule = new() { TimeSpan.FromHours(9), // 上午9点 TimeSpan.FromHours(14.5), // 下午2点半 TimeSpan.FromHours(18) // 下午6点 }; private readonly SemaphoreSlim _executionLock = new(1, 1); // 防止并发执行 public ExchangeScheduledPollingService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { var now = DateTime.Now; var today = now.Date; // 计算下一次执行时间:优先取当天未到的时间点,否则取次日第一个时间点 var nextRunTime = _dailySchedule .Select(t => today.Add(t)) .FirstOrDefault(t => t > now) ?? today.AddDays(1).Add(_dailySchedule.First()); // 等待到执行时间 await Task.Delay(nextRunTime - now, stoppingToken); if (stoppingToken.IsCancellationRequested) break; // 执行同步API调用(加锁避免并发) await _executionLock.WaitAsync(stoppingToken); try { ExecuteScheduledApiCall(); } catch (Exception ex) { // 记录异常日志,根据需求决定是否重试 Console.WriteLine($"定时调用失败:{ex.Message}"); } finally { _executionLock.Release(); } } } // 同步执行API调用的核心逻辑 private void ExecuteScheduledApiCall() { var client = _httpClientFactory.CreateClient("ExchangeWcfApi"); var request = new HttpRequestMessage(HttpMethod.Get, "/定时查询接口"); var response = client.Send(request); response.EnsureSuccessStatusCode(); // 同步处理响应 using var stream = response.Content.ReadAsStream(); using var reader = new StreamReader(stream); var content = reader.ReadToEnd(); // ... 后续业务逻辑处理 } }注册后台服务
在Program.cs中注册该服务,让宿主自动管理其生命周期:builder.Services.AddHostedService<ExchangeScheduledPollingService>();关键注意事项
- 任务隔离:如果多个API需要不同的调度时间,建议为每个API创建独立的
BackgroundService,避免任务互相影响。 - 日志监控:对所有调用的请求参数、响应内容、异常信息做完整日志记录,便于排查问题和合规审计。
- 取消支持:所有异步等待逻辑都绑定
CancellationToken,确保服务停止时能优雅终止任务。
- 任务隔离:如果多个API需要不同的调度时间,建议为每个API创建独立的
内容的提问来源于stack exchange,提问作者beast
相关产品推荐
相关产品推荐

