使用||運營商,微軟介紹了這裏短路評價Short Circuit EvaluationVisual Studio C#和短路評估
不過,我有以下的代碼,這似乎違背了這一過程:
if ((_opcLoaded || DoLoadOPC()) &&
(_tagsAdded || DoAddTags()) &&
DoWriteRecipe() &&
(DoResume()))
我試圖阻止來自被稱爲如果_tagsAdded功能DoAddTags是真實的(DoAddTags設置_tagsAdded爲true)。
但是,我發現即使在_tagsAdded
爲真時也會調用DoAddTag
。 _opcLoaded
和DoLoadOPC
的情況也是如此。我必須在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 ==真
很難揭開這個表達式的可能的副作用。只要不寫不可讀的代碼,這需要更多的if語句。 –
無法重現您的問題中指定的行爲。你確定這些字段之前沒有設置爲false嗎? –
你確定DoAddTags被調用嗎?也許它是從其他地方調用的。我檢查了Debug,如果_tagsAdded爲true,則不會調用DoAddTags。在DoAddTags中放置一個剎車點並檢查_tagsAdded是否爲真。如果是這樣,請檢查CallStack是否從您期望的位置調用。 –