Можно ли получить число потоков в очереди, ожидающих с Monitor.Enter? - PullRequest
1 голос
/ 19 октября 2019

Я использую код Singleton, который не является потокобезопасным и требует времени для запуска. Иногда он может вызываться одновременно несколькими пользователями, поэтому я использую Monitor для обработки очереди обработки запросов, как показано ниже:

bool lockWasTaken = false;
try
{
    Monitor.TryEnter(lockObject, ref lockWasTaken); // returns lockWasTaken = true if it can get a lock
    if (!lockWasTaken)
    {
        log.Warn("Locked by existing request. Request is queued.");
        Monitor.Enter(lockObject, ref lockWasTaken); // Goes into the queue to access the object
    }

    // Do the Singleton processing

}
catch(Exception ex)
{
    log.Fatal(ex);
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(lockObject);
    }
}

Это все работает хорошо. Но я хотел бы иметь возможность регистрировать, сколько запросов в очереди. Возможно ли это?

1 Ответ

1 голос
/ 19 октября 2019

Спасибо за @Theodor Zoulias за то, что он указал мне правильное направление для решения ниже, используя класс Interlocked;

private static readonly Object lockObject = new Object(); // just a random object used to decide whether the thread has locked the Singleton functions
private static int queueCount = 0; // tracked across multiple threads

bool lockWasTaken = false;
try
{
    // Increments the queueCount variable across multiple threads
    // https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=netframework-4.8
    int currentQueueCount = Interlocked.Increment(ref queueCount);

    Monitor.TryEnter(lockObject, ref lockWasTaken); // returns lockWasTaken = true if it can get a lock
    if (!lockWasTaken)
    {
        log.Warn("Locked by existing request. Request is queued. Queue length is " + (currentQueueCount - 1).ToString()); // subtract since the first request is already processing
        Monitor.Enter(lockObject, ref lockWasTaken); // Goes into the queue to access the object
    }

    // Do the Singleton processing

}
catch(Exception ex)
{
    log.Fatal(ex);
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(lockObject);
    }
    // Reduce the queue count
    Interlocked.Decrement(ref queueCount);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...