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

如何在指定时间自动调用ASP.NET Core中的[HttpPost]接口

服务器端定时触发HttpPost请求的解决方案

你之前用的代码是WinForms的Timer,这套逻辑在ASP.NET Core服务器环境里根本跑不起来,原因有这几点:

  • WinForms的Timer依赖UI线程,服务器端没有这个线程,Tick事件根本不会触发
  • 用_ran这种全局变量记录执行状态,服务器重启、应用池回收或者多实例部署时,状态直接丢失,没法保证任务只执行一次
  • ASP.NET Core是无状态的服务器框架,这种桌面程序的定时逻辑完全不适用

下面给你两种适合服务器端的实现方案:


方案一:用BackgroundService轻量实现

这是ASP.NET Core官方推荐的后台任务方案,结合System.Timers.Timer实现定时检查,同时用持久化方式记录任务执行状态。

1. 创建后台服务类

using Microsoft.Extensions.Hosting;
using System.Timers;
using System.Runtime.Caching;

public class ScheduledPostService : BackgroundService
{
    private Timer _timer;
    private readonly ILogger<ScheduledPostService> _logger;
    private readonly HttpClient _httpClient;

    public ScheduledPostService(ILogger<ScheduledPostService> logger, HttpClient httpClient)
    {
        _logger = logger;
        _httpClient = httpClient;
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // 每分钟检查一次时间(可根据需求调整间隔)
        _timer = new Timer(60000);
        _timer.Elapsed += OnTimerElapsed;
        _timer.Start();

        _logger.LogInformation("定时任务服务已启动");
        return Task.CompletedTask;
    }

    private async void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        _timer.Stop(); // 先停Timer,避免并发执行
        try
        {
            var now = DateTime.Now;
            // 检查是否到11点整,且今日未执行过任务
            if (now.Hour == 11 && now.Minute == 0 && !HasJobRunToday())
            {
                _logger.LogInformation("开始执行定时HttpPost请求");
                // 替换成你的实际接口地址
                var response = await _httpClient.PostAsync("/api/your-target-endpoint", null);
                
                if (response.IsSuccessStatusCode)
                {
                    _logger.LogInformation("HttpPost请求执行成功");
                    MarkJobAsRunToday(); // 标记今日已执行
                }
                else
                {
                    _logger.LogError("请求失败,状态码:{Code}", response.StatusCode);
                }
            }
            // 每天7点重置执行标记
            else if (now.Hour == 7 && now.Minute == 0)
            {
                ResetJobRunMark();
                _logger.LogInformation("已重置今日执行标记");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "定时任务执行出错");
        }
        finally
        {
            _timer.Start(); // 重启Timer
        }
    }

    // 用内存缓存记录执行状态,生产环境建议换成Redis或数据库
    private bool HasJobRunToday()
    {
        var cacheKey = $"DailyRun_{DateTime.Today:yyyyMMdd}";
        return MemoryCache.Default.Get(cacheKey) != null;
    }

    private void MarkJobAsRunToday()
    {
        var cacheKey = $"DailyRun_{DateTime.Today:yyyyMMdd}";
        // 缓存到次日过期
        MemoryCache.Default.Set(cacheKey, true, DateTime.Today.AddDays(1));
    }

    private void ResetJobRunMark()
    {
        var cacheKey = $"DailyRun_{DateTime.Today:yyyyMMdd}";
        MemoryCache.Default.Remove(cacheKey);
    }

    public override void Dispose()
    {
        _timer?.Dispose();
        base.Dispose();
    }
}

2. 注册服务到Program.cs

var builder = WebApplication.CreateBuilder(args);

// 注册HttpClient(避免手动new导致连接泄漏)
builder.Services.AddHttpClient();
// 注册后台定时服务
builder.Services.AddHostedService<ScheduledPostService>();

// 其他服务配置...

var app = builder.Build();

// 中间件配置...

app.Run();

方案二:用Quartz.NET实现复杂定时规则

如果需要更灵活的调度(比如每周一执行、按cron表达式配置),可以用专业的定时任务框架Quartz.NET。

1. 安装NuGet包

Install-Package Quartz
Install-Package Quartz.Extensions.Hosting

2. 创建任务类

using Quartz;

public class PostRequestJob : IJob
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<PostRequestJob> _logger;

    public PostRequestJob(HttpClient httpClient, ILogger<PostRequestJob> logger)
    {
        _httpClient = httpClient;
        _logger = logger;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("开始执行Quartz定时HttpPost请求");
        var response = await _httpClient.PostAsync("/api/your-target-endpoint", null);
        
        if (response.IsSuccessStatusCode)
        {
            _logger.LogInformation("请求执行成功");
        }
        else
        {
            _logger.LogError("请求失败,状态码:{Code}", response.StatusCode);
        }
    }
}

3. 配置Quartz到Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpClient();

// 配置Quartz
builder.Services.AddQuartz(q =>
{
    // 注册任务
    var jobId = new JobKey("DailyPostJob");
    q.AddJob<PostRequestJob>(opts => opts.WithIdentity(jobId));

    // 配置触发器:每天11点执行(cron表达式)
    q.AddTrigger(opts => opts
        .ForJob(jobId)
        .WithIdentity("DailyPostTrigger")
        .WithCronSchedule("0 0 11 * * ?")); // cron语法:分 时 日 月 周 年(可选)
});

// 注册Quartz托管服务
builder.Services.AddQuartzHostedService(opts => opts.WaitForJobsToComplete = true);

// 其他配置...

var app = builder.Build();

// 中间件配置...

app.Run();

注意事项

  • 服务器端要注意应用池回收问题,建议配置应用池禁用定期回收,或者用Quartz的持久化功能保存任务状态
  • 内存缓存的执行标记在应用重启后会丢失,生产环境一定要用Redis、数据库等分布式存储
  • 必须通过依赖注入获取HttpClient,禁止手动实例化,否则会造成TCP连接泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 11:43:22