Offending code:
object _objLock = new object();
bool _isCurrentlyUpdatingValues = false;
public void UpdateTestReadValuesTimerCallback(object state)
{
try
{
lock (_objLock)
{
if (_isCurrentlyUpdatingValues == true)
{
return;
}
_isCurrentlyUpdatingValues = true;
}
foreach (var prop in CommConfigDnp3.Dnp3Properties)
{
if (prop.ReadOrWrite == ReadOrWrite.Read)
{
if (prop.PropertyType == PropertyType.Bool)
{
bool? value = CommConfigDnp3.ReadBinary(prop.PropertyName);
prop.LastValue = value;
}
else
{
double? value = CommConfigDnp3.ReadDouble(prop.PropertyName);
prop.LastValue = value;
}
}
}
}
finally
{
_isCurrentlyUpdatingValues = false;
}
On breakpoint there is 3 threads into the foreach. I thought it wouldn't be possible. I though that there only could be 1 at the time. What's my bug?
The method is is called on timer each 10 seconds. When I debug the 10 seconds timer timeout happen quickly so many threads calls the method in a debug session but I though only one at a time could reach the foreach loop. Please explain why I have 3 or more? See selected threads in attached image where it shows 3 threads in the foreach (directly in the foreach or somewhere in the callstack of the foreach).
Please note that I know I could have used SpinLock but that is not part of my problem.
CodePudding user response:
Use a local method variable to indicate work can proceed, and only set it to true
if the lock is acquired.
try
{
bool doWork = false;
lock (_objLock)
{
if (!_isCurrentlyUpdatingValues)
{
_isCurrentlyUpdatingValues = true;
doWork = true;
}
}
if (doWork)
{
// do work here...
lock (_objLock)
{
_isCurrentlyUpdatingValues = false;
}
}
}
catch
{
lock (_objLock)
{
_isCurrentlyUpdatingValues = false;
}
throw;
}