2009-03-13 3 views
8

Разве это не будет излишним и только один из них необходим? Я искал и нашел разные сообщения о взаимном исключении и замках в C# here и here.

Пример:
В нашем приложении у нас есть функция, которая объединяет несколько потоков повторного подключения и внутри этой нити мы используем Mutex и lock. Разве lock не блокирует доступ к этому разделу кода и предотвращает обновление connect от любого другого потока?Должны использоваться замки и мьютексы в C#

bool connect = false; 
Mutex reconnectMutex = new Mutex(false, "Reconnect_" + key); 

try 
{ 
    lock(site) 
    { 
     if(site.ContainsKey(key)) 
     { 
     siteInfo = (SiteInfo)site[key]; 
     if(reconnectMutex.WaitOne(100, true)) 
     { 
      connect = true; 
     } 
     } 
    } 

    if (connect) 
    { 
     // Process thread logic 
    } 
} 
catch 
{} 

reconnectMutex.ReleaseMutex(); 

Дополнительная информация:
Это находится во WebService ASP.NET не работает в веб-сада.

ответ

11

Этот Mutex (поскольку он имеет имя) остановит любой процесс на том же компьютере, что и его доступ, тогда как блокировка остановит только другие потоки в том же процессе. Я не вижу в этом примере кода, почему вам нужны оба вида блокировки. Кажется хорошей практикой держать простой замок в течение короткого периода времени, но тогда гораздо более тяжелый межпроцессный мьютекс заблокирован для более длительного (хотя и перекрывающего) периода! Было бы проще просто использовать мьютекс. И, возможно, выяснить, действительно ли требуется межпроцессорная блокировка.

Кстати, catch {} - это совсем не то, что нужно использовать в этом сценарии. Вы должны использовать finally { /* release mutex */ }. Они очень разные. Улов будет проглотить гораздо больше видов исключения, чем это необходимо, а также будет вызывать вложенные наконец обработчиков для выполнения в ответ на исключения низкого уровня, таких как повреждение памяти, нарушение прав доступа и т.д. Таким образом, вместо:

try 
{ 
    // something 
} 
catch 
{} 

// cleanup 

вы должны иметь:

try 
{ 
    // something 
} 
finally 
{ 
    // cleanup 
} 

И если есть конкретные исключения вы можете оправиться от, вы можете поймать их:

try 
{ 
    // something 
} 
catch (DatabaseConfigurationError x) 
{ 
    // tell the user to configure the database properly 
} 
finally 
{ 
    // cleanup 
} 
+0

он должен быть назван соответствующим образом, чтобы быть специфичным для машины. –

+0

Хороший вопрос, я надеюсь, уточнил, что в первом предложении. –

+0

Вы говорите, что я должен исключить инструкцию catch и заменить ее наконец? –

3

«замок» в основном только синтаксический сахар для Montor.Enter/Exit. Mutex - это многопроцессорная блокировка.

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

Однако, в вашем случае, я думаю, вам может быть лучше смотреть в Семафор и монитор. Не похоже, что вам нужно блокировать процессы, поэтому они, вероятно, являются лучшим выбором в этой ситуации.

1

Вы не дали достаточно информации, чтобы действительно ответить на это. Как уже было сказано Earwicker, Mutex позволяет синхронизировать процессы. Таким образом, если у вас есть два экземпляра одного и того же приложения, вы можете сериализовать доступ. Вы можете сделать это, например, при использовании внешних ресурсов.

Теперь вы блокируете сайт, защищая сайт от доступа другими потоками в том же процессе. Это может быть неудобно в зависимости от того, что делают другие методы/потоки. Теперь, если это единственное место, где сайт блокируется, тогда да, я думаю, что это слишком много.

2

Как указывали другие, Mutex блокирует процессы, а локальная блокировка (Monitor) блокирует только те потоки, которые принадлежат текущему процессу. Однако ...

Код, который вы указали, имеет довольно серьезную ошибку.Похоже, что вы освобождаете Mutex безоговорочно в конце (т. Е. reconnectMutex.ReleaseMutex()), но Mutex получен только тогда, когда site.ContainsKey() возвращает true.

Так что если site.ContainsKey возвращает false, то высвобождение Mutex собирается выбросить ApplicationException, потому что вызывающий поток не имеет Mutex.

+0

Спасибо - я обнаружил, что ошибка после того, как я разместил это. Я не мог понять, почему приложение просто закрывается - вот в чем проблема. –

Смежные вопросы