Я пытаюсь устранить неполадки в процессе, который таинственным образом останавливается, и я пытаюсь определить, может ли у нас возникнуть проблема с кэшированием переменной и ее повторным чтением.
В моем сценарии у меня есть операция, которая выполняется по таймеру (я назову ее Poll
), и пара внешних функций, которые вызываются, чтобы сигнализировать о начале и остановке внешней операции. Из-за деталей, которые не стоит вдаваться в подробности, этот гипотетический класс не хочет, чтобы операция Poll выполнялась, если выполняется внешняя операция. Кроме того, внешняя операция может выполняться несколько раз одновременно, поэтому я использую счетчик, чтобы указать количество выполняемых операций.
Текущая логика выглядит более или менее похоже на этот упрощенный пример:
class MyClass
{
private int operationsInProgress;
private void Poll() // Pretend we have a timer in place that's calling this periodically
{
var inProgress = operationsInProgress;
if (inProgress > 0) return;
DoSomething();
}
public void StartExternalOperation()
{
Interlocked.Increment(ref operationsInProgress);
}
public void EndExternalOperation()
{
Interlocked.Decrement(ref operationsInProgress);
}
}
Предположения:
- И
StartExternalOperation
, иEndExternalOperation
вызываются одинаковое количество раз — они выполняются внутриtry...finally
, и нет пути, который оставил бы осиротевшийStart
там. - В какой-то момент после неопределенного количества выполнений
DoSomething()
больше никогда не вызывается. В моем реальном сценарии я не знаю точно почему, но я устранил все другие причины, которые смог найти, кроме этой.
Возможно ли, что я не использую какой-либо забор (ни через переменную Interlocked
, ни через переменную volatile
) в операции чтения, что значение кэшируется, а фактическая переменная больше не читается?
Поскольку это проблема, которую мы не можем надежно воспроизвести, мне нужно знать, может ли то, что я подозреваю, быть причиной. Я мог бы изменить код, чтобы использовать что-то более формальное, например ReaderWriterLock
(или Slim
), и я знаю, что у меня будет правильная логика, мне просто нужно знать, может ли то, что я описал, быть законной причиной.
Poll
вызывается? Я видел что-то подобное при использованииSystem.Timers.Timer
, и оказалось, что таймер выдавал исключение (о котором никогда не сообщалось, потому что обработчик событий таймера подавляет исключения). Но вы сказали, что используетеSystem.Threading.Timer
. Хм . . . Может быть,Interlocked.Add(ref operationsInProgress, 0);
будет полезен? - person Jim Mischel   schedule 23.12.2016System.Threading.Timer
кэшированию энергонезависимых переменных (аналогично тому, как если бы вы запустили поток с бесконечным циклом и проверили значение этой переменной внутри цикла ). - person Adam Robinson   schedule 23.12.2016Poll()
. - person Jim Mischel   schedule 23.12.2016