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

.NET 5下ConcurrentBag多线程应用竞态条件排查及设计模式优化问询

多设备异步处理流程优化问题

背景

过去几个月我一直在尝试优化一个使用DispatcherTimer定期检查资源是否需要更新/处理的流程:资源(即Product)更新后,要将其移动到下一处理步骤,而资源不一定能立即就绪。
我遇到的阻碍分为两点:

  • 当前流程为同步实现,我希望改造为异步架构
  • 我卡壳的模块看起来是很常见的设计模式,但我无法简洁描述问题,因此无法从搜索引擎获取有效解决方案
    需要特别说明的是,我通过直连USB访问这些Product,使用LibUsbDotNet完成设备交互,且已经将USB连接改为异步实现,可同时连接多个Product、并行处理任意数量的设备。

相关代码

public class Product
{
    public bool IsSoftwareUpdated = false;
    public bool IsProductInformationCorrect = false;
    public bool IsEOLProcessingCompleted = false;

    public Product(){}
    ~Product(){}
}

public class ProcessProduct
{
    List<Product> bagOfProducts                   = new List<Product>(new Product[10]);

    ConcurrentBag<Product> UnprocessedUnits       = new ConcurrentBag<Product>();
    ConcurrentBag<Product> CurrentlyUpdating      = new ConcurrentBag<Product>();
    ConcurrentBag<Product> CurrentlyVerifyingInfo = new ConcurrentBag<Product>();
    ConcurrentBag<Product> FinishedProcessing     = new ConcurrentBag<Product>();

    DispatcherTimer _timer = new DispatcherTimer();

    public ProcessProduct()
    {
        _timer.Tick += Timer_Tick;                            //每1秒调用Timer_Tick
        _timer.Interval = new TimeSpan(0,0,1);                //1秒定时器
        
        bagOfProducts.ForEach(o => UnprocessedUnits.Add(o));  //将所有产品放入未处理队列
    
        StartProcessing();
    }
    private void StartProcessing()
    {
        _timer.Start();
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        ProductOrganizationHandler();

        foreach(Product prod in CurrentlyUpdating.ToList())
        {
            UpdateProcessHandler(prod);  //使用await的异步函数
        }
        foreach(Product prod in CurrentlyVerifyingInfo.ToList())
        {
            VerifyingInfoHandler(prod);  //使用await的异步函数
        }
        if(FinishedProcessing.Count == bagOfProducts.Count)
        {
            _timer.Stop();  //所有产品处理完成后停止流程
        }
    }
    
    private void ProductOrganizationHandler()
    {
        //逐个从各ConcurrentBag中取出Product,根据当前处理完成的步骤移动到对应队列
        //如果当前步骤未完成则放回原队列
        //例如:所有未处理单元从UnprocessUnits移动到CurrentlyUpdating或CurrentlyVerifying等
        //如果产品完成更新,则从CurrentlyUpdating移动到CurrentlyVerifying或FinishedProcessing
    }
    private async void UpdateProcessHandler(Product prod)
    {
        await Task.Delay(1000).ConfigureAwait(false);
        //实际逻辑:验证USB通信,执行USB更新
    }
    private async void VerifyingInfoHandler(Product prod)
    {
        await Task.Delay(1000).ConfigureAwait(false);
        //实际逻辑:执行处理逻辑,通过USB与产品通信
    }
}

咨询问题

  1. 这段代码是否存在会造成实际影响的竞态条件?尤其是ProductOrganizationHandler()逻辑,以及Timer_Tick()中遍历ConcurrentBag的逻辑,毕竟Timer_Tick()每秒触发一次。目前这段代码大多数场景下能正常运行,但我担心如果出现ProductOrganizationHandler()执行耗时超过1秒的极端情况,会触发难以排查的偶发竞态条件bug。
  2. 这类流程有没有更适配的设计模式?C#是我接触的第一门面向对象语言,我都是在工作中自学的,我的日常工作大多是嵌入式C开发,没有系统学习过面向对象设计模式。

核心需求

当USB设备就绪时,异步完成每台设备的更新、校验、通信操作,当列表内所有产品都处理完成(或触发超时)后结束流程,本项目基于.NET 5开发。

补充解决方案

后续遇到同类问题的开发者可参考该方案:
我之前不了解DispatcherTimer的Tick事件是提交到Dispatcher队列中执行的,也就是说如果当前有Tick事件正在运行,下一个Tick会等待上一个执行完成后才会启动,Timer_Tick本身是单线程串行执行的,不会并发运行。因此我之前担心的几乎所有多线程/并发问题都不存在,我可以将Timer_Tick当做单线程非并发函数处理。另外为了避免Tick事件堆积,我在Timer_Tick开头先执行_timer.Stop(),在方法执行结束后再重启定时器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:45:05