在VS2010 Pro的“构建设置”面板中,有一个带有“优化代码”标签的CheckBox……当然,我想检查它……但出于非常谨慎的考虑,我问了我兄弟,他说没有经过调试检查,并且在C ++中它可能会做会破坏或破坏代码的事情……但是他不了解C#。

所以我的问题是,是否可以在我的发布版本中选中此框,而不必担心会破坏我的代码? 其次,如果可以破坏代码,那么何时何地? 欢迎使用解释链接。

我在说的CheckBox。

===============>>#1 票数:25 已采纳

通常,您将在发行版本中使用此选项。 这样做是安全且主流的。 没有理由害怕在启用优化的情况下发布代码。 启用优化会干扰调试,这是为调试版本禁用优化的一个很好的理由。

===============>>#2 票数:16

这些优化不应真正破坏您的代码。 埃里克·利珀特(Eric Lippert) 在此发表了一篇文章 ,解释了当您打开该标志时会发生什么。 不同应用程序之间的性能提升会有所不同,因此您需要在项目中对其进行测试,以查看是否存在任何明显的差异(在性能方面)。

===============>>#3 票数:7

在发布模式下运行时,可能会发生一些其他情况下不会发生的错误。 臭名昭著的“非易失性标志”浮现在脑海:

flag = false;

Thread t = new Thread(
   o =>
   {
        while(!flag)
        {
           // do stuff
        }
   });
t.Start();

// main thread does some work

flag = true;
t.Join(); // will never return in release mode if flag is not volatile

这是由于编译器优化而发生的,因为flag变量被线程t的核心缓存,因此无法看到flag的更新值。

===============>>#4 票数:3

优化是否应该引入错误? 没有。

优化会引入错误吗? 也许,毕竟没有什么是完美的。

优化是否可以发现代码中始终存在但在关闭时隐藏的错误? 绝对会发生很多。

重要的是要意识到这是一个改变。 就像您要测试是否做了很多更改一样,应该在关闭它们时进行测试。 如果最终版本将它们打开,那么最终测试也必须将它们打开。

===============>>#5 票数:1

明智的例子是,我从硕士论文的一些模拟部分中获得了一段代码。 在其中打开了优化标志的情况下,代码并没有真正破坏程序,但是探路者仅执行一次运行和循环。 (递归代码将自身陷入到路径查找器中的一个循环中,该循环总是在关闭优化标志的情况下中断的)。

因此,是的,优化标志可以使软件的行为有所不同。

===============>>#6 票数:1

在C#中,优化绝不能破坏您的代码。

相反,启用优化功能后,编译器在C#和CIL之间转换时会生成更紧凑的CIL。

我观察到(坦率地说,这很有趣!)。NET <2.0(1.0和1.1)中的C#编译器在没有优化的情况下产生了良好的CIL,而后来的C#编译器(2.0及更高版本)产生了WITH优化。

===============>>#7 票数:0

.net编译器优化可能导致错误。 今天发生在我身上。 我花了几个小时才把它钉好。 代码是:

for (int i = 0; i < list.Count-1; i++) {
  list[i+1].DoSomeThing();
  //some code
  if (someCondition) {
    list.insert(i+1, new Item());
    i++;
  }
}

在某个时候, list[i+1]被寻址为list[i] ,好像它们都指向同一个项目。 这个错误太奇怪了。 该代码在调试模式和发布模式下运行良好,但是当我在Visual Studio外部运行它时,例如。 从.exe文件中,代码崩溃了。 只有关闭编译器优化才能修复它。

===============>>#8 票数:0

在我的情况下,当我打开优化标记时,它无法完成所有操作,因此最终结果中缺少测量点,因此我只是关闭了优化标记以修复该错误:

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<InspectionOperation> 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<MeasuringPoint> 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调用。 仅供参考,使用.NET Framework 4.7会发生此问题。

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

更新:

好的,我发现如果我从方法签名中删除async Task ,便能够重新启用优化标志并使用Parallel.Invoke

    private void ProcessPartialArrayInspectionOperations(IList<InspectionOperation> 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<MeasuringPoint> 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)
                        );

或者,我认为我可以对每个任务使用Task.Run然后等待Task.WhenAll(t1, t2, t3); 如此处所述,但在这种情况下,我没有进行显式的数据库调用,因此我认为它Task.Run用于使用Task.Run而不是Parallel.Invoke尽管此页面确实说明了我的Parallel.Invoke无法完成的原因: Parallel.Invoke不等待异步方法完成

有关详细信息,请参见“ C#中的并发性” https://stephencleary.com/book/

  ask by Vreenak translate from so

未解决问题?本站智能推荐: