.NET 中实现生产者-消费者模型,BlockingCollection<T> 和 Channel<T>使用示例

一、方案对比:不同线程安全集合的适用场景

在这里插入图片描述

二、推荐方案及示例代码

方案 1:使用 BlockingCollection(同步模型)

public class QueueDemo
{
   
   
    private readonly BlockingCollection<int> _blockingCollection = new BlockingCollection<int>();

    private readonly CancellationTokenSource _cts = new CancellationTokenSource();

    public QueueDemo()
    {
   
   
    }

    // 生产者方法
    public void ProduceData()
    {
   
   
        Task.Run(() =>
        {
   
   
            var rnd = new Random();
            while (!_cts.IsCancellationRequested)
            {
   
   
                var item = rnd.Next(1, 100);

                _blockingCollection.Add(item);      // 触发消费者唤醒

                Console
/// <summary> /// 任务状态机核心类,支持单层多层任务流程 /// </summary> public class TaskStateMachine { // 状态定义 public const string TaskCall = "任务呼叫"; public const string TaskMove1 = "任务搬运1段"; public const string TaskMove2 = "任务搬运2段"; public const string ArriveRotary = "任务到达旋转台"; public const string TaskFinished = "任务彻底结束"; // 分层状态前缀 public const string LayerEndPrefix = "任务第"; public const string LayerToCranePrefix = "任务第"; public const string LayerArriveCranePrefix = "任务第"; public const string LayerStackDonePrefix = "任务第"; private string _currentState; private int _currentLayer; private readonly int _totalLayers; private readonly Stack<string> _stateHistory = new Stack<string>(); private readonly Dictionary<string, List<string>> _transitionRules = new Dictionary<string, List<string>>(); public string CurrentState => _currentState; public int CurrentLayer => _currentLayer; public TaskStateMachine(int totalLayers = 1) { if (totalLayers < 1) throw new ArgumentException("总层数不能小于1", nameof(totalLayers)); _totalLayers = totalLayers; _currentState = TaskCall; _currentLayer = 0; _stateHistory.Push(TaskCall); InitializeTransitionRules(); } /// <summary> /// 初始化状态转移规则 /// </summary> private void InitializeTransitionRules() { // 全局状态转移规则 _transitionRules[TaskCall] = new List<string> { TaskMove1 }; _transitionRules[TaskMove1] = new List<string> { TaskMove2 }; _transitionRules[TaskMove2] = new List<string> { ArriveRotary }; // 分层状态转移规则 for (int layer = 1; layer <= _totalLayers; layer++) { string layerEnd = $"{LayerEndPrefix}{layer}层结束"; string toCrane = $"{LayerToCranePrefix}{layer}层去龙门架"; string arriveCrane = $"{LayerArriveCranePrefix}{layer}层到达龙门架"; string stackDone = $"{LayerStackDonePrefix}{layer}层完成堆叠"; // 第一层的特殊入口 if (layer == 1) { _transitionRules[ArriveRotary] = new List<string> { layerEnd }; } _transitionRules[layerEnd] = new List<string> { toCrane }; _transitionRules[toCrane] = new List<string> { arriveCrane }; _transitionRules[arriveCrane] = new List<string> { stackDone }; // 完成堆叠后的转移 if (layer < _totalLayers) { _transitionRules[stackDone] = new List<string> { $"{LayerEndPrefix}{layer + 1}层结束" }; } else { _transitionRules[stackDone] = new List<string> { TaskFinished }; } } // 最终状态无转移 _transitionRules[TaskFinished] = new List<string>(); } /// <summary> /// 尝试状态转移 /// </summary> /// <param name="nextState">目标状态</param> /// <returns>是否转移成功</returns> public bool TryChangeState(string nextState) { // 检查跨层跳跃 if (DetectLayerSkip(_currentState, nextState)) { throw new InvalidOperationException($"检测到非法跨层跳跃: {_currentState} -> {nextState}"); } // 验证状态转移 if (IsValidTransition(nextState)) { _stateHistory.Push(_currentState); _currentState = nextState; // 更新当前层 if (nextState.StartsWith(LayerEndPrefix)) { _currentLayer = ExtractLayerNumber(nextState); } return true; } return false; } /// <summary> /// 验证状态转移是否合法 /// </summary> private bool IsValidTransition(string nextState) { // 检查状态是否在规则中存在 if (!_transitionRules.ContainsKey(_currentState)) { throw new InvalidOperationException($"未知当前状态: {_currentState}"); } // 检查是否在允许的转移列表中 if (_transitionRules[_currentState].Contains(nextState)) { return true; } // 特殊规则:完成堆叠后允许进入下一层或结束 if (IsLayerStackDoneState(_currentState)) { int currentLayer = ExtractLayerNumber(_currentState); // 转移到下一层 if (currentLayer < _totalLayers && nextState == $"{LayerEndPrefix}{currentLayer + 1}层结束") { return true; } // 最后一层转移到结束 if (currentLayer == _totalLayers && nextState == TaskFinished) { return true; } } return false; } /// <summary> /// 检测跨层跳跃 /// </summary> private bool DetectLayerSkip(string currentState, string nextState) { if (IsLayerStackDoneState(currentState) && nextState.StartsWith(LayerEndPrefix)) { int currentLayer = ExtractLayerNumber(currentState); int nextLayer = ExtractLayerNumber(nextState); // 只允许+1层跳跃 return nextLayer != currentLayer + 1; } return false; } /// <summary> /// 从状态字符串提取层号 /// </summary> private int ExtractLayerNumber(string state) { if (state.StartsWith(LayerEndPrefix)) { int start = LayerEndPrefix.Length; int end = state.IndexOf("层"); if (end > start) { string numStr = state.Substring(start, end - start); if (int.TryParse(numStr, out int layer)) { return layer; } } } return 0; } /// <summary> /// 检查是否为完成堆叠状态 /// </summary> private bool IsLayerStackDoneState(string state) { return state.StartsWith(LayerStackDonePrefix) && state.EndsWith("完成堆叠"); } /// <summary> /// 回退到上一个状态 /// </summary> public void RollbackState() { if (_stateHistory.Count > 1) { _stateHistory.Pop(); // 移除当前状态 _currentState = _stateHistory.Peek(); // 更新层号 if (_currentState.StartsWith(LayerEndPrefix)) { _currentLayer = ExtractLayerNumber(_currentState); } } } /// <summary> /// 获取当前状态描述 /// </summary> public string GetStatusDescription() { return _totalLayers > 1 ? $"当前状态: {_currentState}, 当前层: {_currentLayer}/{_totalLayers}" : $"当前状态: {_currentState}"; } } 以上逻辑,如果我想让第一层能第二层的流程能交叉起来,这样能节约时间,我要如何更改呢
最新发布
12-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值