Метод синхронизации объекта был вызван из несинхронизированного блока кода - PullRequest
1 голос
/ 30 сентября 2011

Я получаю исключение в производственной среде с сообщением «Метод синхронизации объектов был вызван из несинхронизированного блока кода» на Mutex.ReleaseMutex () в следующем коде:

Mutex Mutex
{
    get { return mutex ?? (mutex = new Mutex(false, mutexName)); }
}
[NonSerialized]
Mutex mutex;

public void Log(/*...*/)
{
    Mutex.WaitOne();
    try
    {
        /*...*/
    }
    finally
    {
        Mutex.ReleaseMutex();
    }
}

Могут быть процессы сохранения, которые могутиспользовать мьютексы с разными и одинаковыми mutextName.И все же я не уверен, как это исключение может произойти там.

1 Ответ

7 голосов
/ 30 сентября 2011

Этот код:

Mutex Mutex
{
    get { return mutex ?? (mutex = new Mutex(false, mutexName)); }
}

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

Thread A        |  Thread B
-------------------------------------
Enters
Is Null? (yes)   Enters
Create Mutex     Is Null? (yes) <- Thread A hasn't assigned it yet.
Assign mutex     Create Mutex
Use Mutex        Assign mutex  <- Oops! We just overwrote the mutex thread A created!
Release Mutex <- Oops! We are trying to release the mutex Thread B created without owning it!

Надеемся, что иллюстрация не является мусором.

Использование класса System.Lazy<T> - это потокобезопасный способ выполнения отложенной инициализации,если вы действительно хотите сделать это с вашим мьютексом.

private Lazy<Mutex> _lazyMutex = new Lazy<Mutex>(() => new Mutex(false, "MyMutex"));
Mutex Mutex
{
    get { return _lazyMutex.Value; }
}

Учитывая это, почему вы пытаетесь лениво инициализировать свой Mutex?Как вы избавляетесь от этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...