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

C# 基于Microsoft.AspNetCore.Owin的Web API如何存储客户端任务运行状态

实现方案

1 不要直接在Controller中存储状态

ASP.NET Core中控制器默认是瞬态(Transient)生命周期,每次请求都会创建新的控制器实例,你在控制器内声明的普通字段/属性会在每次请求结束后销毁,无法跨请求共享状态。如果声明为静态字段虽然可以实现共享,但会导致代码耦合度极高、无法单元测试、并发控制逻辑难以维护,不推荐使用。

2 推荐方案:注入单例并发状态服务

你可以自定义一个线程安全的状态管理类,注册为全局单例,再注入到控制器中使用,步骤如下:

2.1 定义状态实体和状态管理服务

首先定义任务状态的实体类,再封装基于ConcurrentDictionary(.NET 自带的线程安全字典)的状态管理逻辑:

// 任务状态实体
public class WorkerTaskState
{
    public string TaskId { get; set; }
    public DateTime AssignTime { get; set; }
    public bool IsCompleted { get; set; }
}

// 状态管理服务接口,方便后续单元测试替换实现
public interface IWorkerTaskStateService
{
    // 获取指定worker的任务状态
    WorkerTaskState GetWorkerState(string workerName);
    // 给worker分配新任务,返回新任务
    WorkerTaskState AssignNewTask(string workerName);
}

// 内存实现的状态管理服务
public class MemoryWorkerTaskStateService : IWorkerTaskStateService
{
    // 线程安全字典,key为workerName,value为对应的任务状态
    private readonly ConcurrentDictionary<string, WorkerTaskState> _workerStates = new();

    public WorkerTaskState GetWorkerState(string workerName)
    {
        _workerStates.TryGetValue(workerName, out var state);
        return state;
    }

    public WorkerTaskState AssignNewTask(string workerName)
    {
        var newState = new WorkerTaskState
        {
            TaskId = Guid.NewGuid().ToString("N"),
            AssignTime = DateTime.Now,
            IsCompleted = false
        };
        // AddOrUpdate是原子操作,存在则更新,不存在则添加
        _workerStates.AddOrUpdate(workerName, newState, (key, old) => newState);
        return newState;
    }
}

2.2 注册服务为全局单例

在你的启动类中注册服务,确保整个应用生命周期内只有一个服务实例,状态可以跨请求保持:

  • 如果是Startup.cs的写法,在ConfigureServices方法中添加:
services.AddSingleton<IWorkerTaskStateService, MemoryWorkerTaskStateService>();
  • 如果是.NET 6+的顶层语句Program.cs写法,直接在builder阶段添加:
builder.Services.AddSingleton<IWorkerTaskStateService, MemoryWorkerTaskStateService>();

2.3 在控制器中注入使用

修改你的TaskController,注入状态服务即可直接在接口中调用:

[ApiController]
[Route("[controller]")]
public class TaskController : ControllerBase
{
    private readonly IWorkerTaskStateService _stateService;

    // 构造函数注入服务
    public TaskController(IWorkerTaskStateService stateService)
    {
        _stateService = stateService;
    }

    [HttpGet]
    public IActionResult Get(string workerName)
    {
        if (string.IsNullOrWhiteSpace(workerName))
            return Ok("Empty");
        
        var existState = _stateService.GetWorkerState(workerName);
        // 该worker没有分配过任务,或者上一个任务已完成,可以分配新任务
        if (existState == null || existState.IsCompleted)
        {
            var newTask = _stateService.AssignNewTask(workerName);
            return Ok(new { TaskId = newTask.TaskId, Msg = "新任务分配成功" });
        }
        // 还有未完成的任务,返回现有任务
        return Ok(new { TaskId = existState.TaskId, Msg = "已有进行中的任务" });
    }
}

3 注意事项

  • 内存存储的状态会在服务重启、进程退出时丢失,如果需要持久化状态,可以将服务的实现替换为数据库存储即可,上层业务代码不需要修改。
  • 如果你有多个连续的状态操作需要保证原子性,可以在服务内部加锁处理,避免并发冲突。
  • 你可以根据业务需求扩展WorkerTaskState的字段,比如存储任务内容、超时时间等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:09:02