2017-06-20 91 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