Are there risks to optimizing code in C#?

后端 未结 8 825
粉色の甜心
粉色の甜心 2020-12-18 18:53

In the build settings panel of VS2010 Pro, there is a CheckBox with the label \"optimize code\"... of course, I want to check it... but being unusually cautious, I asked my

8条回答
  •  有刺的猬
    2020-12-18 19:29

    In my case when I had the optimizations flag turned on it would not complete all the operations so there were measuring points missing in the final result so I simply turned the optimization flag off to fix the bug:

    using System.Threading.Tasks;
    
                    Parallel.Invoke(
                        async () => await ProcessPartialArrayOperationAssets(operationAssets, 0, operationAssets.Count / 2,
                            operations, inspection1),
                        async () => await ProcessPartialArrayOperationAssets(operationAssets, operationAssets.Count / 2,
                            operationAssets.Count, operations, inspection1)
                    );
    
    private async Task ProcessPartialArrayInspectionOperations(IList operations,
        int begin,
        int end,
        Inspection inspection,
        InspectionAsset inspectionAsset)
    {
        await Task.Run(() =>
        {
            // create one new operation measuring point for each measuring point in the operation's equipment
            int itemCounter = begin + 1;
    
            for (int i = begin; i < end; i++)
            {
                lock (_thisLock)
                {
                    InspectionOperation operation = operations[i];
                    int itemNumber = 1;
    
                    // get the asset
                    InspectionAsset operationAsset = operation.OperationAsset;
                    if (operationAsset != null)
                    {
                        // get the measuring points
                        string ABAPTrue = Abap.ABAP_TRUE;
    
                        lock (_thisLock)
                        {
                            IList measuringPoints = DbContext.MeasuringPoints.Where(x =>
                                    x.AssetID == operationAsset.AssetID && x.InactiveFlag != ABAPTrue)
                                .ToList();
    
                            if (measuringPoints != null)
                            {
                                //Debug.WriteLine("measuringPoints.Count = " + measuringPoints.Count);
    
                                // create the operation measuring points
                                foreach (MeasuringPoint measuringPoint in measuringPoints)
                                {
                                    OperationMeasuringPoint operationMeasuringPoint =
                                        new OperationMeasuringPoint
                                        {
                                            InspectionID = inspection.InspectionID,
                                            OperationNumber = operation.OperationNumber,
                                            SubActivity = "",
                                            RoutingNo = "",
                                            ItemNumber = itemNumber.ToString("D4"),
                                            // e.g. "0001", "0002" and so on
                                            ItemCounter = itemCounter.ToString("D8"),
                                            // e.g. "00000001", "00000002" and so on
                                            MeasuringPointID = measuringPoint.MeasuringPointID,
                                            MeasuringPointDescription = measuringPoint.Description,
                                            Equipment = inspectionAsset.AssetID,
                                            Category = "P"
                                        };
                                    DbContext.Entry(operationMeasuringPoint).State = EntityState.Added;
                                    itemNumber++;
                                    itemCounter++;
                                }
                            }
                        }
                    }
                }
            }
        });
    }
    

    Thus I replaced the Parallel.Invoke call with this as well. FYI, this problem occurred using .NET Framework 4.7.

    await ProcessPartialArrayOperationAssets(operationAssets, 0, operationAssets.Count, operations, inspection1);
    

    UPDATE:

    OK, I've found that I was able to re-enable the optimization flag and use Parallel.Invoke if I remove the async Task from the method signature:

        private void ProcessPartialArrayInspectionOperations(IList operations,
            int begin,
            int end,
            Inspection inspection,
            InspectionAsset inspectionAsset)
        {
            // create one new operation measuring point for each measuring point in the operation's equipment
            int itemCounter = begin + 1;
    
            for (int i = begin; i < end; i++)
            {
    
                InspectionOperation operation = operations[i];
                int itemNumber = 1;
    
                // get the asset
                InspectionAsset operationAsset = operation.OperationAsset;
                if (operationAsset != null)
                {
                    // get the measuring points
                    string ABAPTrue = Abap.ABAP_TRUE;
    
                    lock (_thisLock)
                    {
                        IList measuringPoints = DbContext.MeasuringPoints.Where(x =>
                                x.AssetID == operationAsset.AssetID && x.InactiveFlag != ABAPTrue)
                            .ToList();
    
                        if (measuringPoints != null)
                        {
                            //Debug.WriteLine("measuringPoints.Count = " + measuringPoints.Count);
    
                            // create the operation measuring points
                            foreach (MeasuringPoint measuringPoint in measuringPoints)
                            {
                                OperationMeasuringPoint operationMeasuringPoint =
                                    new OperationMeasuringPoint
                                    {
                                        InspectionID = inspection.InspectionID,
                                        OperationNumber = operation.OperationNumber,
                                        SubActivity = "",
                                        RoutingNo = "",
                                        ItemNumber = itemNumber.ToString("D4"),
                                        // e.g. "0001", "0002" and so on
                                        ItemCounter = itemCounter.ToString("D8"),
                                        // e.g. "00000001", "00000002" and so on
                                        MeasuringPointID = measuringPoint.MeasuringPointID,
                                        MeasuringPointDescription = measuringPoint.Description,
                                        Equipment = inspectionAsset.AssetID,
                                        Category = "P"
                                    };
                                DbContext.Entry(operationMeasuringPoint).State = EntityState.Added;
                                itemNumber++;
                                itemCounter++;
                            }
                        }
                    }
                }
            }
        }
    
                            Parallel.Invoke(
                                () => ProcessPartialArrayInspectionOperations(operations, 0, operations.Count / 2,
                                    inspection1, inspectionAsset),
                                () => ProcessPartialArrayInspectionOperations(operations, operations.Count / 2,
                                    operations.Count, inspection1, inspectionAsset)
                            );
    

    Alternatively, I think I could use Task.Run for each and then a await Task.WhenAll(t1, t2, t3); as explained here, but in this case I am not making explicit database calls so I don't think it applies to use Task.Run instead of Parallel.Invoke though this page does explain why my Parallel.Invoke was not completing: Parallel.Invoke does not wait for async methods to complete

    For details, please see "Concurrency in C#" https://stephencleary.com/book/

提交回复
热议问题