枚举时集合已更改;可能的解决方法可以停止并重新开始?

时间:2019-07-16 23:04:50

标签: c# exception foreach collections unhandled-exception

我正在创建一个航空大亨游戏。在这个游戏中,我正在计算每个不同航班上的乘客人数。为此,我运行了一个复杂的公式来比较每次飞行的各个方面。 (如果航班竞争)

每次用户(或AI)更改可能影响填充度的内容时,都会重新计算填充度。考虑添加航班,更改价格,更改客机的座位图等。当游戏重新计算一组竞赛飞行的填充度时,所有以前的填充度都将被删除,计算将从零开始,然后一个一个地填充所有填充度。 (计算中不使用一次飞行的填充度)

这是我假设发生错误的地方:游戏正忙于比较7个飞行,并且在此过程中,玩家添加了一个飞行(或更改了任何飞行的值),这意味着集合已更改。

我当时认为最好的解决方案可能是告诉游戏停止当前迭代并重新开始。但是我该怎么做呢?还是有更好的解决方案?

很抱歉,很长的代码段。在此先感谢您对我的帮助!

GetPassengers每天都会被调用。如果特定航班的填充度值为空,则计算将被调用到 填写它们。如果已填写,它将跳过计算并继续 直接达到所需的值。

public static List<FlightClassItem> GetPassengers(PoolFlight flight, PassengerRoute route)
{
        _clock.Reset();
        _clock.Start();

        var classes = new List<FlightClassItem>();

        var value = FlightFillingDegreeValues.GetElement(v => v.Departure == flight.DepartureAirport && v.Destination == flight.Destination && v.Airline == flight.Airliner.Owner.Airline);

        if (value == null)
        {
            GetOverflowTable(route, flight.DepartureAirport);

            value = FlightFillingDegreeValues.GetElement(v => v.Departure == flight.DepartureAirport && v.Destination == flight.Destination && v.Airline == flight.Airliner.Owner.Airline);
        }

        foreach (ClassTypeEnum classType in Enum.GetValues(typeof(ClassTypeEnum)))
        {
            if((int)classType <= GameTimeObject.GetInstance().GameTime.Year)
            {
                classes.Add(new FlightClassItem()
                {
                    FarePrice = route.Classes.First(c => c.Type == classType).Price,
                    Capacity = flight.Airliner.getAirlinerClassCapacity(classType),
                    Type = classType,
                    FillingDegree = value.FillingDegrees[classType],
                    Passengers = (int)value.ClassPax[classType]["Business"] + value.ClassPax[classType]["Tourist"],
                    BusinessPassengers = value.ClassPax[classType]["Business"],
                    HolidayPassengers = value.ClassPax[classType]["Tourist"]

                });
            }
        }

        _clock.Stop();
        double time = _clock.ElapsedTicks;

        return classes;
}

GetOVerflowTable是计算的表面。在此之下 计算是很多子计算,并且有很多foreach飞行  循环。这些foreach循环都不会更改航班的任何值,当然也不会添加或删除任何航班或机舱等级。

private static void GetOverflowTable(PassengerRoute route, Airport departure)
{
        Airport destination = route.Airport1 == departure ? route.Airport2 : route.Airport1;

        var season = PassengerHelpers.GetCurrentSeason(route.Airport1);
        var distance = MathHelpers.GetDistance(departure, destination);

        double touristDemand = 0;
        double businessDemand = 0;
        double cityTripDemand = 0;

        var allRoutes = Routes.GetElements(r => (r.Airport1 == route.Airport1 && r.Airport2 == route.Airport2) || (r.Airport2 == route.Airport1 && r.Airport1 == route.Airport2));

        var flights = allRoutes.SelectMany(r => r.Pool.Flights.Where(f => f.DepartureAirport == departure && (r.Type == RouteTypeEnum.Passenger || r.Type == RouteTypeEnum.Mixed_Passenger || r.Type == RouteTypeEnum.Mixed)));

        Dictionary<PoolFlight, FlightFillingDegreeValue> values = new Dictionary<PoolFlight, FlightFillingDegreeValue>();

        if (flights.Count() > 0)
        {
            var flight = flights.First();
            foreach (ClassTypeEnum classType in GetOrderedClassTypes())
            {
                double basePrice = CalculateBasePrice(route, classType);
                int supply = GetRouteSupply(route, classType);
                double sdf = GetSupplyDemandFactor(route, classType, supply);

                touristDemand += PassengerHelpers.GetHolidayPassengersDemand(departure, destination, season, null)
                    * GetAirlinerClassDistanceFactor(distance, classType, "Tourist");
                businessDemand += PassengerHelpers.GetBusinessPassengersDemand(departure, destination, null)
                    * GetAirlinerClassDistanceFactor(distance, classType, "Business");
                cityTripDemand += PassengerHelpers.GetCityPassengersDemand(departure, destination, season, null)
                    * GetAirlinerClassDistanceFactor(distance, classType, "City");

                Dictionary<EnumPassengerType, double> flightComparisonTotals = new Dictionary<EnumPassengerType, double>();

                if ((int)classType <= GameTimeObject.GetInstance().GameTime.Year)
                {
                    foreach (EnumPassengerType paxType in Enum.GetValues(typeof(EnumPassengerType)))
                    {
                        double comparisonFactorTotal = 0;
                        comparisonFactorTotal = flights.Sum(f => GetFlightComparisonFactor(f, route, classType, paxType, basePrice, sdf));

                        flightComparisonTotals.Add(paxType, comparisonFactorTotal);
                    }
                }


                var classSupplyDemandOverflowValues = GetSupplyDemandOverflowValues(flight, route, classType, basePrice, sdf, flightComparisonTotals);

                flightComparisonTotals.Clear();

                foreach (var tflight in flights)
                {

                    if (!values.ContainsKey(tflight))
                        values.Add(tflight, new FlightFillingDegreeValue()
                        {
                            Departure = tflight.DepartureAirport,
                            Destination = tflight.Destination,
                            Airline = tflight.Airliner.Owner.Airline,
                            ClassPax = new Dictionary<ClassTypeEnum, Dictionary<string, int>>(),
                            FillingDegrees = new Dictionary<ClassTypeEnum, double>()
                        });

                    if (tflight.Airliner.Classes.Any(c => c.Type == classType))
                    {
                        var clTouristDemand = classSupplyDemandOverflowValues[tflight][EnumPassengerType.Holiday_tourist];
                        var clBusinessDemand = classSupplyDemandOverflowValues[tflight][EnumPassengerType.Business];
                        var clCityTripDemand = classSupplyDemandOverflowValues[tflight][EnumPassengerType.City_trip_tourist];

                        touristDemand -= clTouristDemand;
                        businessDemand -= clBusinessDemand;
                        cityTripDemand -= clCityTripDemand;

                        if((clTouristDemand + clBusinessDemand + clCityTripDemand) > flight.Airliner.getAirlinerClassCapacity(classType))
                        {
                            if(clCityTripDemand > 0)
                            {
                                clCityTripDemand--;
                                cityTripDemand++;
                            }
                            else if (clBusinessDemand > 0)
                            {
                                clBusinessDemand--;
                                businessDemand++;
                            }
                            else
                            {
                                clTouristDemand--;
                                touristDemand++;
                            }
                        }

                        values[tflight].ClassPax.Add(classType, new Dictionary<string, int>());
                        values[tflight].ClassPax[classType].Add("Tourist", clTouristDemand + clCityTripDemand);
                        values[tflight].ClassPax[classType].Add("Business", clBusinessDemand);

                        double classFillingDegree = 0;

                        if (flight.Airliner.getAirlinerClassCapacity(classType) > 0)
                        {
                            classFillingDegree = Math.Min(1,(clTouristDemand + clCityTripDemand + clBusinessDemand) / flight.Airliner.getAirlinerClassCapacity(classType));
                        }


                        values[tflight].FillingDegrees.Add(classType, classFillingDegree);

                    }
                    else
                    {

                        values[tflight].ClassPax.Add(classType, new Dictionary<string, int>());
                        values[tflight].ClassPax[classType].Add("Tourist", 0);
                        values[tflight].ClassPax[classType].Add("Business", 0);

                        double classFillingDegree = 0;

                        values[tflight].FillingDegrees.Add(classType, classFillingDegree);
                    }
                }


            }

            foreach (var value in values)
            {
                FlightFillingDegreeValues.Add(value.Value);
            }
        }
}

例如,如果玩家在航线上添加航班,则在此我们重置路线上每个航班的填充度。它使我共享的第一个函数中的Value为0,因此调用了计算。

public static void ResetAirlineFlightFillingDegrees(Route route)
{
        if(route.Type == RouteTypeEnum.Passenger || route.Type == RouteTypeEnum.Mixed || route.Type == RouteTypeEnum.Mixed_Passenger)
        {
            FlightFillingDegreeValues.RemoveElements(r => r.Departure == route.Airport1 && r.Destination == route.Airport2);
            FlightFillingDegreeValues.RemoveElements(r => r.Destination == route.Airport1 && r.Departure == route.Airport2);

            var allRoutes = Routes.GetElements(r => (r.Airport1 == route.Airport1 && r.Airport2 == route.Airport2) || (r.Airport2 == route.Airport1 && r.Airport1 == route.Airport2));

            var flights = allRoutes.SelectMany(r => r.Pool.Flights.Where(f => f.Airliner.Type.TypeAirliner == AirlinerType.TypeOfAirliner.Passenger || f.Airliner.Type.TypeAirliner == AirlinerType.TypeOfAirliner.Mixed || f.Airliner.Type.TypeAirliner == AirlinerType.TypeOfAirliner.Seaplane ));


            foreach (var flight in flights)
            {
                AIModel.FlightLoadHelpers.GetPassengers(flight, route as PassengerRoute);
            }

        }

        if (route.Type == RouteTypeEnum.Cargo || route.Type == RouteTypeEnum.Mixed || route.Type == RouteTypeEnum.Mixed_Passenger)
        {
            CargoFlightFillingDegreeValues.RemoveElements(r => r.Departure == route.Airport1 && r.Destination == route.Airport2);
            CargoFlightFillingDegreeValues.RemoveElements(r => r.Destination == route.Airport1 && r.Departure == route.Airport2);

            var allRoutes = Routes.GetElements(r => (r.Airport1 == route.Airport1 && r.Airport2 == route.Airport2) || (r.Airport2 == route.Airport1 && r.Airport1 == route.Airport2));

            var flights = allRoutes.SelectMany(r => r.Pool.Flights.Where(f => f.Airliner.Type.TypeAirliner == AirlinerType.TypeOfAirliner.Cargo || f.Airliner.Type.TypeAirliner == AirlinerType.TypeOfAirliner.Mixed));


            foreach (var flight in flights)
            {
                AIModel.FlightLoadHelpers.GetCargo(flight, route as CargoRoute);
            }
        }
}

崩溃发生在计算中的随机位置。这次,它在此函数的第一行中崩溃了:(整个解决方案的任何地方都没有更改classtypeEnum)

private static double GetVideoLevel(ClassTypeEnum type, PoolFlight flight)
{
        AirlinerClass aclass = flight.Airliner.Classes.First(c => c.Type == type);

        double basefactor = 1.3;
        double classfactor = 0;

        if (type == ClassTypeEnum.Economy_Class)
            classfactor = 0;
        if (type == ClassTypeEnum.Premium_Economy_Class)
            classfactor = -0.1;
        if (type == ClassTypeEnum.Business_Class)
            classfactor = -0.2;
        if (type == ClassTypeEnum.First_Class)
            classfactor = -0.3;

        double level = basefactor + (aclass.Video.QualityLevel.Level + aclass.Video.SizeLevel.Level + aclass.Video.Facility.BaseValue) * aclass.Video.Options.Sum(v => v.Level);

        return level + classfactor + (aclass.Video.UseAdvertisements ? -0.2 : 0);
}

错误:

  

System.InvalidOperationException:'逐字显示是gewijzigd。莫吉耶克(Mogelijk)创造了新的时代。'

已翻译:集合已修改。可能未执行枚举。

0 个答案:

没有答案