在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

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

6回复

C#编译器是否足够聪明以优化此代码?

请忽略此问题中的代码可读性。 在性能方面,应将以下代码编写为: 或像这样: ? 编辑: criteria是一个class , MaxResults是一个简单的整数属性(即public int MaxResults { get { return _maxResult
2回复

C#编译器会优化此代码吗?

我经常遇到这种情况。 乍一看,我认为,“这是糟糕的编码; 我正在执行一个方法两次并且必然会得到相同的结果。“但是在想到这一点时,我不得不怀疑编译器是否像我一样聪明并且可以得出相同的结论。 编译器的行为是否依赖于GetOtherThing方法的内容? 说它看起来像这样(有点类似于我现
6回复

如何在编译/优化后看到C#代码?

当我从深度的C#中看到一个示例章节时,我正在阅读关于yield关键字: http : //csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx 。 第一个代码块使用yield关键字来创建一个简单的迭代器。
3回复

MS C#编译器和非优化代码

注意:我在发布的示例中发现了一些错误 - 编辑修复它 如果不启用优化,官方C#编译器会做一些有趣的事情。 例如,一个简单的if语句: 如果优化,会变成以下内容: 但如果我们禁用优化,它会变成这样: 我无法理解这一点。 为什么所有额外的代码,似乎在源中不存在?
4回复

C#属性访问优化

在C#(或VB .NET)中,编译器是否尝试优化属性访问? 例如, 我想如果编译器能够以某种方式检测到View在两次访问之间保持不变,它可以避免两次计算该值。 是否进行了这些优化? 我知道如果View有一些密集的计算,它可能应该重构为一个函数( GetView() )。 在我
1回复

为什么有人应该禁用编译器优化

一位不再在这里工作的同事不久前禁用了我们其中一个项目的代码优化。 我再也无法与他联系,并且查看他在提交时所做的更改,我看不出他为什么这样做的任何原因。 我们的程序存在一些巨大的瓶颈,即使我不确定再次启用此选项是否可以提高性能,我还是说这是更好的方法。 这里的主要问题是,我们将不得不
4回复

'|' vs'||' C#中的编译器优化

我最近在一次采访中被问到这个问题,我完全错了,但让我对C#和.net中的编译器优化感到好奇 请考虑以下代码段: 运行上面的结果会得到以下结果: 按位或使用时的结果: 功能A正在执行。 功能B正在执行。 真正 使用或运算符时的结果:
4回复

在什么级别C#编译器或JIT优化应用程序代码?

我想知道这些信息以减少我的代码大小,所以我不会浪费时间来优化将由编译器或JIT完成的事情。 例如: 如果我们假设编译器内联调用属性的get函数,那么我不必将返回值保存在局部变量中以避免函数调用。 我想推荐一个描述正在发生的事情的好参考?
4回复

C#编译器或Jitter会优化这些算术运算吗?

假设我有这样的事情: 基本上转向: 进入这个: 我不确定是否可以在不改变程序结果的情况下进行这种更改,但是想知道C#编译器或抖动是否做了类似的事情? 如果没有,为什么? 我认为它不值得,或者它们还没有添加这个优化。
1回复

什么是.NET / C#中的轻松例外?

在Reflector中查看它时,我在程序集上找到了CompilationRelaxations属性。 此链接表示该属性指定是否: 优化器被授予额外的宽容度以放宽异常。 什么是宽松的异常以及编译器在给出“额外纬度”的情况下做了什么。