Вопрос

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

На данный момент у меня нет точного текста исключения, но это тоже было не очень полезно.

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

  • SyncObject не равен нулю
  • SyncObject еще не заблокирован

Будет ли это иметь какое-либо отношение к вызываемому абоненту, работающему в STA (однопоточная квартира) или MTA (многопоточная квартира)?

Это было полезно?

Решение

От эта страница:

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

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

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

Итак, как вы можете прочитать, похоже, что в условиях ограниченных ресурсов мы можем получать исключения, генерируемые методом Ввода монитора, который lock (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

используется, например, сВзаимосвязано.Сравните обмен, где вы меняете, например,Нитки.Текущий.Управляемый идентификатор потока или что-то еще, отличное от нуля?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top