stevenjin 2024-12-11 17:27 采纳率: 96.8%
浏览 20
已结题

在c#中异步多任务并发访问的问题

以下会用界面启动多个异步多任务,当任务较多时,会出现同时修改一个变量的情况吧?如果用锁,这种情形只能用SemaphoreSlim吗?求正确处理方案。


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();
        }
    }
}

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.");
    }
}

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.");
    }
}
  • 写回答

2条回答 默认 最新

  • wanghui0380 2024-12-11 18:54
    关注

    会出现同时修改一个变量的情况吧?
    那有变量?你是指 ConcurrentDictionary _cancellationTokenSources这个?这玩意是线程安全字典,他本身就是线程安全
    另外说一句,如果是官方类带Concurrent这个开头都是已经做了线程安全的东西

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
    1人已打赏
查看更多回答(1条)

报告相同问题?

问题事件

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