2017-06-20 112 views
0

使用||运营商,微软介绍了这里短路评价Short Circuit EvaluationVisual Studio C#和短路评估

不过,我有以下的代码,这似乎违背了这一过程:

if ((_opcLoaded || DoLoadOPC()) && 
    (_tagsAdded || DoAddTags()) && 
    DoWriteRecipe() && 
    (DoResume())) 

我试图阻止来自被称为如果_tagsAdded功能DoAddTags是真实的(DoAddTags设置_tagsAdded为true)。

但是,我发现即使在_tagsAdded为真时也会调用DoAddTag_opcLoadedDoLoadOPC的情况也是如此。我必须在DoAddTags内部检查_tagsAdded,这不应该是必需的。

有人可以解释为什么会发生这种情况吗?

下面是完整的代码

// 
         // Resume a Paused recipe 
        case MonitoredTasks.Resume: 
         Task.Factory.StartNew(() => 
          { 
           MonitoredTask = MonitoredTasks.None; 
           if ((_opcLoaded || DoLoadOPC()) && 
             **(_tagsAdded || DoAddTags())** && 
             DoWriteRecipe() && 
             (DoResume())) 
           { 
            MonitoredTask = MonitoredTasks.None; 
            RunningState = RecipeRunningStates.Running; 
            Status = CIPStatuses.Running; 
           } 
           else 
           { 
            MonitoredTask = MonitoredTasks.Resume; 
           } 
          }); 

         break; 

而对于DoAddTags

 /// <summary> 
    /// Adds all necessary tags to the OPC Server Manager 
    /// </summary> 
    /// <returns></returns> 
    bool DoAddTags() 
    { 

     bool result = false; 
     var oldActivity = Activity; 
     // 
     // Not doing anything OPC related? 
     if (Activity != CIPActivities.AddingOPCTags && !_tagsAdded && Activity != CIPActivities.StartingOPC) 
     { 
      lock (_locks[LOCK_OPC]) 
      { 
       Activity = CIPActivities.AddingOPCTags; 
       Status = CIPStatuses.Initialising; 
       RecipeError = Errors.None; 
       try 
       { 
        // 
        // Reset connection and internal tags list 
        _serverManager.Reset(); 

        // 
        // Now to add all OPC Tags - Area 
        CIPStatusTag = _serverManager.AddTag(_area.CIPStatusTag); 
        RecipeIDTag = _serverManager.AddTag(_area.RecipeIDTag); 
        RecipeInstructionIDTag = _serverManager.AddTag(_area.RecipeInstructionIDTag); 
        HandshakingTag = _serverManager.AddTag(_area.HandshakingTag); 
        GlobalInstructionIDTag = _serverManager.AddTag(_area.GlobalInstructionIDTag); 
        InstructionAttemptsTag = _serverManager.AddTag(_area.InstructionAttemptsTag); 

        // 
        // Area tags OK? 
        if (CIPStatusTag == null || RecipeIDTag == null || RecipeInstructionIDTag == null || HandshakingTag == null || GlobalInstructionIDTag == null || InstructionAttemptsTag == null) 
        { 
         RecipeError = Errors.InvalidAreaTags; 
         DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags - Invalid AREA Tags"), Sender = this }); 
        } 
        else 
        { 

         VM_CIPInstruction vm = null; 
         bool instructionTagErrors = false; 
         // 
         // For each area instruction that is used, assig a link to the instruction 
         foreach (var i in _areaInstructions) 
         { 
          // 
          // Create a View Model for the specified area instruction : this allows us to determine the number of parameters (tags) that apply to the instruction 
          vm = new VM_CIPInstruction(i.Value.Instruction); 
          // 
          // Assign device reference tags 
          if (vm.DeviceReferencesAvailable) 
          { 
           i.Value.DeviceTag = _serverManager.AddTag(i.Value.Instruction.DeviceReferenceTag); 
           instructionTagErrors = i.Value.DeviceTag == null; 
          } 
          // 
          // For each required parameter, add tag 
          for (int paramNo = 1; paramNo <= vm.NoOfParams; paramNo++) 
          { 
           switch (paramNo) 
           { 
            case 1: 
             // 
             // Tag defined? Add it 
             if (vm.AreaInstruction.Param1Tag >= 0) 
             { 
              i.Value.Param1 = _serverManager.AddTag(i.Value.Instruction.Param1Tag); 

              if (i.Value.Param1 == null) 
              { 
               instructionTagErrors = true; 
              } 
             } 
             else 
             { 
              instructionTagErrors = true; 
             } 
             break; 
            case 2: 
             // 
             // Tag defined? Add it 
             if (vm.AreaInstruction.Param2Tag >= 0) 
             { 
              i.Value.Param2 = _serverManager.AddTag(i.Value.Instruction.Param2Tag); 

              if (i.Value.Param2 == null) 
              { 
               instructionTagErrors = true; 
              } 
             } 
             else 
             { 
              instructionTagErrors = true; 
             } 
             break; 
            case 3: 
             // 
             // Tag defined? Add it 
             if (vm.AreaInstruction.Param3Tag >= 0) 
             { 
              i.Value.Param3 = _serverManager.AddTag(i.Value.Instruction.Param3Tag); 

              if (i.Value.Param3 == null) 
              { 
               instructionTagErrors = true; 
              } 
             } 
             else 
             { 
              instructionTagErrors = true; 
             } 
             break; 
            case 4: 
             // 
             // Tag defined? Add it and then check quality 
             if (vm.AreaInstruction.Param4Tag >= 0) 
             { 
              i.Value.Param4 = _serverManager.AddTag(i.Value.Instruction.Param4Tag); 

              if (i.Value.Param4 == null) 
              { 
               instructionTagErrors = true; 
              } 
             } 
             else 
             { 
              instructionTagErrors = true; 
             } 
             break; 

            case 5: 
             // 
             // Tag defined? Add it and then check quality 
             if (vm.AreaInstruction.Param5Tag >= 0) 
             { 
              i.Value.Param5 = _serverManager.AddTag(i.Value.Instruction.Param5Tag); 

              if (i.Value.Param5 == null) 
              { 
               instructionTagErrors = true; 
              } 
             } 
             else 
             { 
              instructionTagErrors = true; 
             } 
             break; 

            case 6: 
             // 
             // Tag defined? Add it and then check quality 
             if (vm.AreaInstruction.Param6Tag >= 0) 
             { 
              i.Value.Param6 = _serverManager.AddTag(i.Value.Instruction.Param6Tag); 

              if (i.Value.Param6 == null) 
              { 
               instructionTagErrors = true; 
              } 
             } 
             else 
             { 
              instructionTagErrors = true; 
             } 
             break; 
           } 
          } 

          if (instructionTagErrors) 
          { 
           RecipeError = Errors.InvalidInstructionTags; 
           DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage(String.Format("CIPRecipe.DoAddTags - Invalid Instruction {0} Tags", vm.Name)), Sender = this }); 
           break; 
          } 
         } 
         // 
         // Any problems adding tags? 
         if (RecipeError == Errors.None) 
         { 
          Activity = CIPActivities.StartingOPC; 
          // 
          // Once all tags added, start OPC Server 
          result = _serverManager.Start(); 

          if (!result) 
          { 
           Status = CIPStatuses.AddTagsFailed; 
           RecipeError = Errors.OPC; 
           DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags - Start of OPC failed"), Sender = this }); 
          } 
          else 
          { 
           **_tagsAdded = true;** 
           Status = CIPStatuses.TagsAdded; 
          } 
         } 
         else 
         { 
          Status = CIPStatuses.AddTagsFailed; 
         } 
        } 
       } 
       catch (Exception ex) 
       { 
        RecipeError = Errors.Exception_AddTags; 
        DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags"), Exception = ex, Sender = this }); 
       } 
       finally 
       { 
        Activity = oldActivity; 
       } 
      } 
     } 
     return Status == CIPStatuses.TagsAdded; 
    } 

我已经强调了相关线路有**

在第一遍DoAddTags的代码被执行, _tagsAdded设置为TRUE-我在这里放置了一个断点,所以我知道它正在设置。不久之后(有或没有前一个断点)DoAddTags再次进入(在第一行),尽管_doAddTags == true。

我甚至在代码“(_tagsAdded || DoAddTags())”上设置了一个断点。 _tagsAdded == true,但仍然输入DoAddTags。

那么我现在看到的是,所有的手表/调试信息是一致的是,DoAddTags被调用,同时_tagsAdded ==真

+2

很难揭开这个表达式的可能的副作用。只要不写不可读的代码,这需要更多的if语句。 –

+0

无法重现您的问题中指定的行为。你确定这些字段之前没有设置为false吗? –

+0

你确定DoAddTags被调用吗?也许它是从其他地方调用的。我检查了Debug,如果_tagsAdded为true,则不会调用DoAddTags。在DoAddTags中放置一个刹车点并检查_tagsAdded是否为真。如果是这样,请检查CallStack是否从您期望的位置调用。 –

回答

2

此代码将不会显示您所描述的行为,短期电路正如所描述的那样工作。

实际发生的:_tagsAdded最初false,所以DoAddTags()被调用,这台_tagsAddedtrue

然后调试器开始,你检查_tagsAdded,看看它的true

而是使用F11逐步执行代码并检查或观察所有相关变量。

+0

对不起,但你错了。 1 - 我在条目DoAddTags上有一个断点。 2 - 我有一个关于_tagsAdded的手表 3 - 当第二次点击断点时,_doAddTags为true。即尽管短路,功能已被输入。 4 - 我部门的所有开发人员(20岁以上)无法解释行为。 –

+0

if(Activity!= CIPActivities.AddingOPCTags &&!_tagsAdded) 这是DoAddTags中的第一行。 _tags添加,第二次重复为TRUE。短路还没有被应用,否则这个代码不会被称为 –

+1

不,我没有错。 [见这个Ideone](http://ideone.com/M5GXNP)。我正在处理你给我们的东西。如果你没有提供[mcve],这个答案就像它将要得到的那样接近。你或者有一些线程问题,或者调试器对你说谎,或者其他许多问题。也许增加一些日志记录来记录程序中某些点的值。 – CodeCaster