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

C#异步灯泡生产模拟程序在await处崩溃,求故障原因

问题原因与修复方案

核心崩溃原因

  1. 主线程未正确等待异步入口方法
    代码最开头直接调用Main();但未使用await,而Main是async Task类型,这会导致主线程不等待异步操作完成就继续执行,当程序执行到await Task.WhenAny(taskList)时,主线程可能提前退出,引发程序无提示终止。

  2. 生产循环无限执行
    startMaschine方法中的while(i<10000)循环体内没有i++语句,导致任务永远无法完成。当用户输入选项2时,Task.WhenAny会一直等待永远不会结束的任务,结合主线程未等待的问题,直接触发程序终止。

  3. Random类线程安全问题
    多个异步任务共用同一个Random实例,而Random并非线程安全类型,多线程环境下调用Next()会导致其内部状态损坏,可能抛出未捕获的异常,进一步导致程序崩溃。

次要功能问题

每次输入选项1启动机器时,都会调用prod.registerObserver(new Observer()),导致Production实例中累积多个Observer,后续检测到次品时会重复打印通知信息。

修复后的完整代码

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace BulbProduction
{
    class Program
    {
        static async Task Main()
        {
            Console.WriteLine("Bulb Production Monitoring!");
            List<Task<string>> taskList = new List<Task<string>>();
            string input = "";
            int maschineID = 1;
            Production prod = new Production();
            // 仅注册一次Observer,避免重复通知
            prod.registerObserver(new Observer());

            Console.WriteLine("1: starts a production maschine");
            Console.WriteLine("2: analyses the results");
            Console.WriteLine("3: exits the production process");

            while (!input.Equals("exit"))
            {
                input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        // 每个任务使用独立的Random实例,避免线程安全问题
                        Random rndGenerator = new Random();
                        taskList.Add(prod.startMaschine(maschineID, rndGenerator));
                        maschineID++;
                        break;
                    case "2":
                        while (taskList.Any())
                        {
                            Task<string> finishedTask = await Task.WhenAny(taskList);
                            // 安全获取结果,处理可能的异常
                            try
                            {
                                string result = await finishedTask;
                                Console.WriteLine(result);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine($"Task failed: {ex.Message}");
                            }
                            taskList.Remove(finishedTask);
                        }
                        break;
                    case "3":
                        input = "exit";
                        break;
                    default:
                        break;
                }
            }
        }
    }

    public class Bulb
    {
        public bool _functionTest;
    }

    public class Production
    {
        private List<Observer> _observerList = new List<Observer>();

        public async Task<string> startMaschine(int maschineId, Random rndGenerator)
        {
            return await Task.Run(async () =>
            {
                Console.WriteLine($"Maschine {maschineId} is ready for use ... ");
                int i = 0;
                int defect = 0;
                // 添加i++,让循环正常结束
                while (i < 10000)
                {
                    int rndNumber = rndGenerator.Next(1, 101);
                    Bulb bulb = new Bulb();
                    await Task.Delay(50);
                    if (rndNumber <= 5)
                    {
                        bulb._functionTest = false;
                        defect++;
                        this.notify(maschineId);
                    }
                    else
                    {
                        bulb._functionTest = true;
                    }
                    i++;
                }
                return $"Maschine {maschineId} has produced {defect} defective bulbs.";
            });
        }

        public void registerObserver(Observer obs)
        {
            _observerList.Add(obs);
        }

        private void notify(int maschineId)
        {
            foreach (Observer obs in _observerList)
            {
                obs.update(maschineId);
            }
        }
    }

    public class Observer
    {
        public void update(int maschineId)
        {
            DateTime localDate = DateTime.Now;
            Console.WriteLine($"Defect bulb identified on maschine {maschineId} at {localDate}.");
        }
    }
}

关键修复点说明

  • 移除了手动调用Main()的代码,让异步Main作为程序入口,确保主线程等待所有异步操作。
  • 在生产循环中添加i++,保证任务能正常完成并返回结果。
  • 每次启动机器时创建独立的Random实例,避免多线程安全问题;也可以使用Random.Shared(.NET Core 3.0+)替代。
  • 仅注册一次Observer,避免重复打印次品通知。
  • 添加了异常捕获逻辑,处理任务执行中可能出现的异常,避免程序意外崩溃。

内容的提问来源于stack exchange,提问作者Z.J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 08:35:05