У меня есть ситуация, когда для тестирования я хочу, чтобы мой метод таймера (FooMethod) запускался по одному за раз. В приведенном ниже примере FooMethod передается как делегат на таймер. Существует много конкретных примеров этого класса. Я думал, что, ставя _locker static, только один экземпляр FooMethod() будет обрабатывать одновременно. Но когда я запускаю приложение, несколько потоков проходят через строку TryEnter() за раз.Monitor.TryEnter с общим классом
Вот как я добавляю каждый класс к новому таймеру. Это делается в цикле, для каждого экземпляра Foo:
_timers.Add(new Timer(foo.FooMethod, null, 0, 10000));
И это класс, который имеет этот метод:
public class Foo<T>
{
private static readonly object _locker = new object();
public void FooMethod(object stateInfo)
{
// Don't let threads back up; just get out
if (!Monitor.TryEnter(_locker)) { return; }
try
{
// Logic here
}
finally
{
Monitor.Exit(_locker);
}
}
}
Примечание: Как правило, _locker не статична; Я не хочу, чтобы тот же самый поток вводил метод до того, как он получил шанс завершить. Я изменил его на статику здесь для тестирования.
Моя первая мысль заключается в том, что, возможно, это не работает, потому что класс является общим? И что каждый конкретный класс на самом деле является его собственным классом, и они не разделяют переменную _locker? Это правда? Если это так, как я должен иметь конкретные классы, разделяющие переменную _locker? Нужно ли добавлять статическую переменную _locker в какой-то другой класс, к которому имеют доступ Foos?
очень интересный и хорошо заданный вопрос. +1 – spender
Обратите внимание, что тот же поток * может * повторно ввести блокировку (но только если есть определенная рекурсия, конечно).Это то, что блокирует для: предотвращения * разных * потоков от использования одного и того же ресурса. – phoog
@spender Спасибо. И я понимаю, что я знаю. Моя цель со статической переменной состояла в том, чтобы предотвратить одновременное обработку нескольких потоков одним и тем же способом. Но это не работает. –