Подтвердить что ты не робот

Заброшенное исключение мьютекса

Я пытаюсь использовать мьютекс в первый раз и выполняю следующий код в двух отдельных экземплярах программы

public void asynchronousCode()
    {
        using (var mutex = new Mutex(false, "mySpecialMutex"))
        {
            if (!mutex.WaitOne(1000, false))
            {
                Console.WriteLine("First check - some one locked the mutex");
            }

            if (!mutex.WaitOne(3000, false))
            {
                Console.WriteLine("Second check- some one locked the mutex");
            }
            else
            {
                Console.WriteLine("I got the mutex");
                Console.WriteLine("sleeping");
                Thread.Sleep(3000);
                Console.WriteLine("Awaking and Releasing mutex");
                mutex.ReleaseMutex();
            }
        }
    }

Когда я запускаю это, один из экземпляров (тот, который я запускаю первым) печатает

I got the mutex
sleeping
awaking and releasing mutex

Другой экземпляр печатает

First check - some one locked the mutex

и как только первый экземпляр арендует мьютекс, он вылетает во второй оператор ожидания с исключением

The wait completed due to an abandoned mutex.

Любые идеи о том, почему я получаю это исключение и как я могу это предотвратить?

Решение. Вероятно, я должен прочитать отчет mdsn более четко. Спасибо, Андрей за то, что указал мне в правильном направлении.

Вы можете использовать метод WaitHandle.WaitOne для запроса права собственности на мьютексы. Поток, которому принадлежит мьютекс, может запросить один и тот же мьютекс при повторных вызовах WaitOne без блокировки его выполнения. Тем не менее, поток должен вызывать метод ReleaseMutex одинаковое количество раз, чтобы освободить право собственности на мьютексы. Класс Mutex обеспечивает идентичность потоков, поэтому мьютекс может быть выпущен только потоком, который его приобрел.

4b9b3361

Ответ 1

Ваша проблема в том, что вы удерживаете Mutex дважды, но только отпустите его один раз, из-за того, как вы неправильно разместили свои операторы if. Ваше первое выполнение ловит его дважды - в обоих этих операторах if, но ваш код только отпускает его один раз.

Вам нужно повторно организовать if, чтобы вы только фиксировали мьютекс один раз.

bool captured = true;
if (!mutex.WaitOne(1000, false))
{
        Console.WriteLine("First check - some one locked the mutex");
        captured = false;
}
if (!captured && !mutex.WaitOne(3000, false))
{
        Console.WriteLine("Second check- some one locked the mutex");
        captured = false;
}
if (captured)
{
        Console.WriteLine("I got the mutex");
        Console.WriteLine("sleeping");
        Thread.Sleep(3000);
        Console.WriteLine("Awaking and Releasing mutex");
        mutex.ReleaseMutex();
}

Ответ 2

Я думаю, что ваша проблема связана с линией using (var mutex = new Mutex(false, "mySpecialMutex")). Когда первый поток завершается, он избавляется от объекта mutex, который, я считаю, может вызвать ошибку, которую вы получаете.

Если возможно, было бы лучше объявить мьютекс как (статическую) переменную класса вне этого метода. Затем вы должны вручную создать экземпляр, прежде чем запускать свои потоки и избавиться от него после их завершения.