stevenjin 2024-12-10 16:51 采纳率: 96.8%
浏览 11
已结题

asp.net core mvc中取消指定任务

1.以下方法,多个任务运行,可以取消指定task。
2.移植到asp.net core mvc后,由于CancellationTokenSource cancellationTokenSourcep放到了方法体的外面,在页面刷新时,cancellationTokenSourcep变量为空,导致无法追踪到token,无法取消任务。将该变量设为静态时,又会取消所有任务。此环境下正确方式是怎样呢?


 static int j = 1;
 static void Main(string[] args)
 {
     var tasks = new Task[3];
     CancellationTokenSource cancellationTokenSource;
     try
     {              
             for (int i = 0; i < 3; i++)
             {
                 // 为每个任务创建单独的 CancellationTokenSource 实例
                 cancellationTokenSource = new CancellationTokenSource();
                 var cancellationToken = cancellationTokenSource.Token;
                 tasks[i] = Task.Run(() =>
                 {
                     // 模拟工作,检查特定任务的取消令牌是否已取消请求(假设你想要取消ID为特定值的任务)
                     while (true) // 循环直到收到取消请求为止(模拟长时间运行的任务)
                     {
                         if (j==10/* 需要取消的条件 */) // 检查是否需要取消当前任务(假设ID为特定值)并作出相应的操作
                         {
                             j = 100;
                             cancellationTokenSource.Cancel(); // 仅取消当前任务关联的取消令牌源对应的任务
                             Console.WriteLine(Task.CurrentId + "取消工作");

                             break; // 任务一旦接收到取消信号,则跳出循环并退出任务
                         }
                         j++;                               
                         Console.WriteLine(Task.CurrentId + "正在工作");  
                         Thread.Sleep(1000); // 模拟工作负载,这里只是一个示例,实际情况下可能会有其他操作或逻辑判断等。
                     } 
                 }, cancellationToken);
             }
       Console.ReadKey();
     }
     catch (Exception ex)
     {

     }          
 }
  • 写回答

2条回答 默认 最新

  • 趣享先生 优质创作者: 编程框架技术领域 2024-12-10 17:10
    关注

    该回答参考ChatGPT,由吾为汝整理提供如若有用,还请题主采纳!

    在 ASP.NET Core MVC 中管理多个任务并能够取消特定任务的确是一个挑战,尤其是在处理任务的生命周期和状态时。由于 ASP.NET Core MVC 是基于请求-响应模型的,任务的管理需要考虑到请求的上下文。以下是一个解决方案,帮助你在 ASP.NET Core MVC 中实现任务的取消。

    解决方案

    1. **使用 IHttpContextAccessor**:通过 IHttpContextAccessor 来存储和访问 CancellationTokenSource,这样可以在请求的上下文中保持对每个任务的引用。

    2. 创建一个服务:将任务管理逻辑封装在一个服务中,以便在控制器中调用。

    实现步骤

    1. 创建任务管理服务

    首先,创建一个任务管理服务来处理任务的创建和取消。

    using System.Collections.Concurrent;
    using System.Threading;
    using System.Threading.Tasks;
    
    public interface ITaskManager
    {
        Task StartTaskAsync(int taskId);
        void CancelTask(int taskId);
    }
    
    public class TaskManager : ITaskManager
    {
        private readonly ConcurrentDictionary<int, CancellationTokenSource> _cancellationTokenSources = new();
    
        public async Task StartTaskAsync(int taskId)
        {
            var cancellationTokenSource = new CancellationTokenSource();
            _cancellationTokenSources[taskId] = cancellationTokenSource;
    
            var cancellationToken = cancellationTokenSource.Token;
    
            await Task.Run(() =>
            {
                while (true)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        Console.WriteLine($"Task {taskId} is cancelled.");
                        break;
                    }
    
                    // 模拟工作
                    Console.WriteLine($"Task {taskId} is working...");
                    Thread.Sleep(1000); // 模拟工作负载
                }
            }, cancellationToken);
        }
    
        public void CancelTask(int taskId)
        {
            if (_cancellationTokenSources.TryRemove(taskId, out var cancellationTokenSource))
            {
                cancellationTokenSource.Cancel();
                cancellationTokenSource.Dispose();
            }
        }
    }
    

    2. 注册服务

    Startup.cs 中注册 ITaskManager 服务:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<ITaskManager, TaskManager>();
        services.AddHttpContextAccessor(); // 注册 IHttpContextAccessor
        services.AddControllersWithViews();
    }
    

    3. 使用服务的控制器

    在控制器中使用 ITaskManager 来启动和取消任务:

    using Microsoft.AspNetCore.Mvc;
    
    public class TaskController : Controller
    {
        private readonly ITaskManager _taskManager;
    
        public TaskController(ITaskManager taskManager)
        {
            _taskManager = taskManager;
        }
    
        public IActionResult StartTask(int taskId)
        {
            _taskManager.StartTaskAsync(taskId);
            return Ok($"Task {taskId} started.");
        }
    
        public IActionResult CancelTask(int taskId)
        {
            _taskManager.CancelTask(taskId);
            return Ok($"Task {taskId} cancelled.");
        }
    }
    

    4. 调用控制器方法

    你可以通过 HTTP 请求来启动和取消任务,例如:

    • 启动任务:GET /Task/StartTask?taskId=1
    • 取消任务:GET /Task/CancelTask?taskId=1

    总结

    通过这种方式,你可以在 ASP.NET Core MVC 中管理多个任务,并能够根据任务 ID 取消特定任务。使用 ConcurrentDictionary 来存储 CancellationTokenSource 实例,确保每个任务都有自己的取消令牌,从而避免了静态变量带来的问题。这样可以有效地管理任务的生命周期,并在需要时进行取消。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 12月18日
  • 已采纳回答 12月10日
  • 创建了问题 12月10日