You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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,确保服务停止时能优雅终止任务。

内容的提问来源于stack exchange,提问作者beast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 09:45:42