2009-11-28 3 views
0

Я написал ком-компонент в .NET, и если я попытаюсь сделать блокировку любого объекта в любом методе (который вызывается неуправляемым кодом, разговаривающим с моим комком-компонентом), я получаю исключение.Когда блокировка (syncObject) вызывает исключение?

В настоящий момент у меня нет точного текста исключения, но это тоже не очень полезно.

Итак, мой вопрос в каких обстоятельствах блокировка (syncObject) может вызвать исключение? Вот некоторые факты:

  • syncObject не является нулевым
  • syncObject еще не заперта

Будет ли это иметь ничего общего с вызываемым работает в STA (Single Резьбовое квартира) или MTA (Multi Резьбовые)?

+3

Какое исключение? Можете ли вы предоставить стек вызовов? – mfeingold

+1

Вам действительно нужно добавить дополнительную информацию и объяснить, как именно вы «вызываете из неуправляемого». –

ответ

2

От this page:

Каждый замок приобретение может вызвать исключение. Будьте готовы к этому.

Большинство шлюзов лениво выделяют событие, если обнаружение блокировки встречает конфликт, включая мониторы CLR. Это распределение может завершиться неудачно при низких ресурсных условиях, в результате чего OOM отправляются из входа в блокировку. (Обратите внимание, что типичная блокировка блокировки не может прерываться с помощью OOM, что позволяет использовать ее в некоторых сценариях с ограниченными ресурсами, таких как внутри CER.) Аналогично, такой сервер, как SQL Server, может выполнять обнаружение блокировки и даже блокировать эти блокировки с помощью генерируя исключения, которые исходят из инструкции Enter, проявляющиеся как System.Runtime.InteropServices.COMException.

Часто не так много, что можно сделать в ответ на такое исключение. Но надежный и безопасный код, который должен иметь дело с отказом, должен учитывать этот случай. Нам бы хотелось, чтобы это было так, что блокирование хостов может быть воспринято разумно, но большинство библиотечных кодов не могут разумно расслабиться в безопасном месте в стеке, чтобы он мог отступить и повторить операцию. В типичном стеке слишком много межбиблиотечного смешения. Вот почему учетные записи на основе тайм-аута с TryEnter обычно представляют собой плохую идею для предотвращения тупиковой ситуации.

Так как вы можете читать, кажется, что в условиях ограниченного ресурса мы можем получить исключения, вызванные методом Enter, который блокирует (o), используя внутренне.

Так что, может быть, ваше решение - это что-то вроде спина-ожидания?

{ 
    uint iters = 0; 
    while (!cond) { 
     if ((++iters % 50) == 0) { 
      // Every so often we sleep with a 1ms timeout (see #30 for justification). 
      Thread.Sleep(1); 
     } else if (Environment.ProcessorCount == 1) { 
      // On a single-CPU machine we yield the thread. 
      Thread.Sleep(0); 
     } else { 
      // Issue YIELD instructions to let the other hardware thread move. 
      Thread.SpinWait(25); 
     } 
    } 
} 

Где Cond может быть какой-то

private volatile int cond = 0 

используется, например, с Interlocked.CompareExchange, где вы меняете, например. Thread.Current.ManagedThreadID или что-то еще отличное от нуля?

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