Для не синхронизированного блока кода вызван метод синхронизации объектов 1с
Я нашел разные статьи об этом исключении, но ни одна из них не была моим случаем. Вот исходный код:
Функция filterCtiCallLog.CreateFilteredCtiCallLogSync(); выполняет запросы к серверу и вызывает некоторые события, одним из которых является событие CtiCallsRetrieve . И мне нужно освободить мьютекс при срабатывании этого события. Но при вызове функции mutex.Release () возникает исключение. CreateFilteredCtiCallLogSync работает синхронно. В чем проблема?
Сохранение логического значения, указывающего, что мьютекс принадлежит владельцу, является серьезной ошибкой. Вы не делаете bool потокобезопасным. Вы попали в этот рассол, потому что используете неправильный объект синхронизации. Мьютекс имеет сходство с потоком, владелец мьютекса - поток. Получивший его поток также должен быть тем, который вызывает ReleaseMutex (). Вот почему ваши кодовые бомбы.
По всей видимости, здесь вам понадобится событие , используйте AutoResetEvent. Создайте его в основном потоке, вызовите Set () в рабочем потоке, WaitOne () в основном потоке, чтобы дождаться, пока рабочий завершит свою работу. А потом утилизируйте его. Также обратите внимание, что использование потока для выполнения задания и ожидание его завершения основным потоком непродуктивно. С таким же успехом вы можете поручить работу основному потоку.
Если вы на самом деле делаете это для защиты доступа к объекту, который не является потокобезопасным (это не ясно), используйте оператор lock .
Я нашел проблему. Прежде всего о классе filterCtiCallLog. Я разработал его так, чтобы он работал как асинхронно, так и синхронно. Сначала я написал код для асинхронного выполнения. Мне нужен был способ инициировать события от дочернего рабочего потока к родительскому, чтобы сообщить о рабочем состоянии. Для этого я использовал класс AsyncOperation и его метод публикации. . Вот часть кода для запуска события CtiCallsRetrieved.
Как видите, код выполняется синхронно. Проблема здесь в методе AsyncOperation.Post() . Я предположил, что если он вызывается в основном потоке, он просто запускает событие, а не отправляет его в родительский поток. Однако это было не так. Я не знаю, как это работает, но я изменил код, чтобы проверить, называется ли CreateFilteredCtiCallLog синхронным или асинхронным. И если это асинхронный вызов, я использовал метод AsyncOperation.Post , если нет, я просто активировал EventHandler , если это не null . Вот исправленный код
Спасибо всем за ответы!
Еще одна причина, по которой может возникнуть это исключение:
Я получаю это исключение в Monitor.Exit, когда после 'await' другой поток продолжает выполнение.
Изменить: Используйте SemaphoreSlim, потому что он не требует, чтобы поток оставался таким же.
У меня было это всего один или два раза, и в каждом случае это происходило из-за попытки освободить мьютекс, которым я не владел.
Вы уверены, что события возникают в том же потоке, в котором был получен мьютекс? Хотя вы упомянули, что filterCtiCallLog.CreateFilteredCtiCallLogSync() является блокирующим вызовом, возможно, он порождает рабочие потоки, которые вызывают событие?
Использование флага для попытки отслеживать состояние синхронизированного объекта ядра просто не сработает - смысл использования этих синхронных вызовов заключается в том, что они работают правильно без какой-либо явной проверки. Установка флагов просто вызовет периодические проблемы, потому что флаг может быть изменен ненадлежащим образом из-за прерываний между проверкой флага и действиями по нему.
Мьютекс может быть освобожден только угрозой, которая его заполучила. Если обратный вызов вызывается другим потоком (внутренним для CreateFilteredCtiCallLogSync () или пула потоков ядра), выпуск завершится ошибкой.
Непонятно, что именно вы пытаетесь сделать. Предположительно, вы хотите сериализовать доступ к CreateFilteredCtiCallLogSync () и флагам обратного вызова, что экземпляр доступен для повторного использования? Если это так, вы можете использовать семафор - init. его на один блок, дождитесь его при запуске и отпустите в обратном вызове.
Есть ли проблема, из-за которой иногда не вызывается обратный вызов и, следовательно, try / finally / release? В таком случае этот выход кажется немного хитрым, если обратный вызов является асинхронным и может быть вызван другим потоком после того, как поток настройки покинул функцию.
Я видел, как это происходит, когда вы блокируете код с помощью монитора, затем вызываете асинхронный код, и вы получаете это, при использовании блокировки (объекта) вы получаете ошибку компилятора, однако между monitor.enter (объект) и Monitor.Exist (объект ) компилятор не жалуется . к сожалению.
Вы также столкнетесь с этим исключением, если сделаете следующее:
Это потому, что код после ожидания может быть выполнен в другом потоке, чем в строке непосредственно перед ним. По сути, кажется, что если вы асинхронизируете код сейчас (в начале 2020 года), мьютексы просто не работают. Используйте события или что-то в этом роде.
Почему нужно указывать объект? Ведь мы можем вообще не использовать этот объект в блоке.
Также чем отличается synchronized(this) от synchronized(o) (я знаю что значит this , чем отличаются блоки с разными объектами)?
И наконец, почему мы можем использовать операции wait , notify и т.п. с Object o , ведь он не поток?
3 ответа 3
Ключевое слово synchronized является утверждением, которое в круглых скобках принимает выражение, возвращающее ссылку на объект. Поэтому его не нужно путать с методом, принимающим один параметр. И то, что используется в скобках - относится к самому утверждению, а не блоку кода, для которого это утверждение работает. Как и в любом другом блоке кода вы можете использовать ссылку на любой объект, если он доступен в области видимости, которая охватывает этот блок. Поэтому какую ссылку вы используете в утверждении synchronized , не имеет отношения к тому, будете ли вы ее использовать в блоке кода или нет.
Вот, что по этому сказано в JLS:
Утверждение synchronized получает блокировку взаимного исключения (§17.1) от имени исполняющего потока, выполняет блок, а затем освобождает блокировку. Пока исполняющий поток владеет блокировкой, ни один другой поток не может получить блокировку.
Тип выражения должен быть ссылочным типом, или возникает ошибка времени компиляции.
И наконец, методы wait() , notify() , и notifyAll() принадлежат классу Object . Поэтому вы можете использовать их в любом классе, вы также можете использовать ссылку на объект, для вызовов этих методов из этого объекта, имеющего эту ссылку. Так как впрочем все унаследованные методы доступны в классе без использования ссылки. Ссылка this указывает на этот объект, поэтому ее указывать необязательно для вызовов наследуемых методов, в то время как для других объектов это необходимо. Поток тоже является объектом, потому, что создается из класса Thread , поэтому если методы вызываются внутри класса, то принадлежат ему.
Я нашел разные статьи об этом исключении, но ни один из них не был моим делом. Вот исходный код:
filterCtiCallLog.CreateFilteredCtiCallLogSync(); выполняет запросы на сервер и вызывает некоторые события, одним из которых является событие CtiCallsRetrieve . И мне нужно освободить мьютекс, когда это событие уволено. Но при вызове вызывается функция исключения mutex.Release(). CreateFilteredCtiCallLogSync работает синхронно. В чем проблема?
ОТВЕТЫ
Ответ 1
Сохранение bool вокруг означает, что мьютекс принадлежит, является серьезной ошибкой. Вы не делаете bool потокобезопасным. Вы попали в этот рассол, потому что используете неправильный объект синхронизации. Мьютекс имеет нить-сродство, владелец мьютекса - это поток. Потоком, который его приобрел, также должен быть тот, который вызывает ReleaseMutex(). Вот почему ваш код бомбит.
Вам, по всей вероятности, нужно событие здесь, используйте AutoResetEvent. Создайте его в основном потоке, вызовите Set() в рабочем, WaitOne() в основном потоке, чтобы дождаться, пока работник выполнит свое задание. И распоряжаться им потом. Также обратите внимание, что использование потока для выполнения задания и наличие основного потока для его завершения не является продуктивным. Вы можете также иметь основной поток выполнить эту работу.
Если вы на самом деле делаете это для защиты доступа к объекту, который не является потокобезопасным (это неясно), используйте оператор блокировки.
Ответ 2
Я нашел проблему. Сначала несколько вещей о классе filterCtiCallLog. Я разработал его так, чтобы работать как асинхронно, так и синхронно. Для первого я написал код для асинхронного выполнения. Мне нужен способ инициировать события из потока дочерних работников родителям, чтобы сообщить о рабочем состоянии. Для этого я использовал AsyncOperation класс и метод post. Вот часть кода для запуска события CtiCallsRetrieved.
Как вы видите, код выполняется синхронно. Проблема здесь в методе AsyncOperation.Post() . Я предположил, что если он вызывается в основном потоке, он будет действовать как просто запуск события, а не размещение его в родительский поток. Однако это было не так. Я не знаю, как он работает, но я изменил код, чтобы проверить, называется ли CreateFilteredCtiCallLog синхронизацией или асинхронным. И если это асинхронный вызов, я использовал метод AsyncOperation.Post , если нет, я просто вызвал EventHandler , если он не null . Вот скорректированный код
Спасибо всем за ответы!
Ответ 3
У меня был только один или два раза, и в каждом случае это произошло, пытаясь освободить мьютекс, которого я не имел.
Вы уверены, что события подняты в том же потоке, на котором был принят мьютекс? Хотя вы отмечаете, что filterCtiCallLog.CreateFilteredCtiCallLogSync() является блокирующим вызовом, возможно, он порождает рабочие потоки, которые поднимают событие?
Ответ 4
Использование флага для попытки контролировать состояние синхронизируемого объекта ядра просто не сработает - точка использования этих синхронных вызовов заключается в том, что они работают корректно без какой-либо явной проверки. Флаги установки просто вызовут прерывистые проблемы, потому что флаг может быть изменен ненадлежащим образом из-за прерываний между проверкой флага и действием на него.
Мьютекс может быть освобожден только той угрозой, которую он приобрел. Если обратный вызов вызывается другим потоком (один внутренний для CreateFilteredCtiCallLogSync() или пул потоков ядра), релиз завершится неудачно.
Не ясно, что именно вы пытаетесь сделать. Предположительно, вы хотите сериализовать доступ к CreateFilteredCtiCallLogSync() и флаги обратного вызова, которые экземпляр доступен для повторного использования? Если это так, вы можете использовать семафор вместо - init. до одного устройства, дождитесь его в начале и отпустите в обратном вызове.
Есть ли проблема, когда иногда callback не вызывается, и, следовательно, try/finally/release? Если так, этот способ кажется немного хитростью, если обратный вызов является асинхронным и может быть вызван другим потоком после того, как поток настройки оставил эту функцию.
Ответ 5
Ответ 6
Я видел это, когда вы блокируете код с помощью монитора, а затем вызываете асинхронный код, и вы получаете это, при использовании блокировки (объекта) вы получаете ошибку компилятора, однако между monitor.enter(object) и Monitor. Exist (объект) компилятор не жалуется. к сожалению.
Я нашел разные статьи об этом исключении, но ни одна из них не была моим случаем. Вот исходный код:
filterCtiCallLog.CreateFilteredCtiCallLogSync(); функция выполняет запросы к серверу и вызывает некоторые события, одно из которых является CtiCallsRetrieve событием. И мне нужно освободить мьютекс при срабатывании этого события. Но при вызове функции mutex.Release () возникает исключение. CreateFilteredCtiCallLogSync работает синхронно. В чем проблема?
Сохранение логического значения, указывающего, что мьютекс принадлежит владельцу, является серьезной ошибкой. Вы не делаете bool потокобезопасным. Вы попали в этот рассол, потому что используете неправильный объект синхронизации. Мьютекс имеет сходство с потоком, владелец мьютекса - поток. Получивший его поток также должен быть тем, который вызывает ReleaseMutex (). Вот почему ваши кодовые бомбы.
Вам, скорее всего, понадобится событие здесь, используйте AutoResetEvent. Создайте его в основном потоке, вызовите Set () в рабочем потоке, WaitOne () в основном потоке, чтобы дождаться, пока рабочий завершит свою работу. А потом утилизируйте его. Также обратите внимание, что использование потока для выполнения задания и ожидание его завершения основным потоком непродуктивно. С таким же успехом вы можете поручить работу основному потоку.
Если вы на самом деле делаете это для защиты доступа к объекту, который не является потокобезопасным (это не ясно), используйте оператор блокировки .
Рассматриваемый мьютекс назван. Исходя из документации Microsoft, это означает, что у него нет сходства потоков. Я не специалист в этом вопросе. На самом деле, я сам получаю ту же ошибку, и мне нужна помощь. Я подниму отдельный вопрос, чтобы задать сценарий.
Это неверно, мьютекс всегда связан с потоками. Именование позволяет использовать мьютекс через границы процесса. Что делает заброшенный мьютекс намного хуже, говорит вам, что процесс неожиданно завершился.
Еще одна причина, по которой может возникнуть это исключение:
Я получаю это исключение в Monitor.Exit, когда после 'await' другой поток продолжает выполнение.
Изменить: используйте SemaphoreSlim, потому что он не требует, чтобы поток оставался таким же.
Я нашел проблему. Прежде всего о классе filterCtiCallLog. Я разработал его так, чтобы он работал как асинхронно, так и синхронно. Сначала я написал код для асинхронного выполнения. Мне нужен был способ инициировать события от дочернего рабочего потока к родительскому, чтобы сообщить о рабочем состоянии. Для этого я использовал класс AsyncOperation и его метод post. Вот часть кода для запуска события CtiCallsRetrieved.
Как видите, код выполняется синхронно. Проблема здесь в AsyncOperation.Post() методе. Я предположил, что если он вызывается в основном потоке, он просто запускает событие, а не отправляет его в родительский поток. Однако это было не так. Я не знаю, как это работает, но я изменил код, чтобы проверить CreateFilteredCtiCallLog , называется ли это синхронизацией или асинхронностью. И если это асинхронный вызов, я использовал AsyncOperation.Post метод, если нет, я просто запустил, EventHandler если это не так null . Вот исправленный код
Спасибо всем за ответы!
Вы также столкнетесь с этим исключением, если сделаете следующее:
Это потому, что код после ожидания может быть выполнен в другом потоке, чем в строке непосредственно перед ним. По сути, кажется, что если вы асинхронизируете код сейчас (в начале 2020 года), мьютексы просто не работают. Используйте события или что-то в этом роде.
Я видел, как это происходит, когда вы блокируете код с помощью монитора, затем вызываете асинхронный код, и вы получаете это, при использовании блокировки (объекта) вы получаете ошибку компилятора, однако между monitor.enter (объект) и Monitor.Exist (объект ) компилятор не жалуется . к сожалению.
Использование флага для попытки отслеживать состояние синхронизированного объекта ядра просто не сработает - смысл использования этих синхронных вызовов заключается в том, что они работают правильно без какой-либо явной проверки. Установка флагов просто вызовет периодические проблемы, потому что флаг может быть изменен ненадлежащим образом из-за прерываний между проверкой флага и действиями по нему.
Мьютекс может быть освобожден только угрозой, которая его заполучила. Если обратный вызов вызывается другим потоком (внутренним для CreateFilteredCtiCallLogSync () или пула потоков ядра), выпуск завершится ошибкой.
Непонятно, что именно вы пытаетесь сделать. Предположительно, вы хотите сериализовать доступ к CreateFilteredCtiCallLogSync () и флагам обратного вызова, что экземпляр доступен для повторного использования? Если это так, вы можете использовать семафор - init. его на один блок, дождитесь его при запуске и отпустите в обратном вызове.
Есть ли проблема, из-за которой иногда не вызывается обратный вызов и, следовательно, try / finally / release? В таком случае этот выход кажется немного хитрым, если обратный вызов является асинхронным и может быть вызван другим потоком после того, как поток настройки покинул функцию.
Я нашел разные статьи об этом исключении, но ни одна из них не была моим случаем. Вот исходный код:
Функция выполняет запросы к серверу и вызывает некоторые события, одним из которых является событие . И мне нужно освободить мьютекс при срабатывании этого события. Но при вызове функции mutex.Release () возникает исключение. работает синхронно. В чем проблема?
Сохранение логического значения, указывающего, что мьютекс принадлежит, - серьезная ошибка. Вы не делаете bool потокобезопасным. Вы попали в этот рассол, потому что используете неправильный объект синхронизации. Мьютекс имеет сходство с потоком, владелец мьютекса - поток. Получивший его поток также должен быть тем, который вызывает ReleaseMutex (). Вот почему ваши кодовые бомбы.
Скорее всего, вам понадобится событие здесь используйте AutoResetEvent. Создайте его в основном потоке, вызовите Set () в рабочем потоке, WaitOne () в основном потоке, чтобы дождаться, пока рабочий завершит свою работу. А потом утилизируйте. Также обратите внимание, что использование потока для выполнения задания и ожидание основного потока его завершения непродуктивно. С таким же успехом вы можете поручить работу основному потоку.
Если вы на самом деле делаете это для защиты доступа к объекту, который не является потокобезопасным (это не ясно), используйте замок заявление.
- Вы правы - я пропустил, что поток, настраивающий обратный вызов, является основным потоком :(
- Рассматриваемый мьютекс назван. Исходя из документации Microsoft, это означает, что у него нет сходства потоков. Я не специалист по этому вопросу. На самом деле, у меня такая же ошибка, и мне нужна помощь. Я подниму отдельный вопрос, чтобы задать сценарий.
- 1 Это неверно, мьютекс всегда связан с потоками. Именование позволяет использовать мьютекс через границы процесса. Что делает заброшенный мьютекс намного хуже, говорит вам, что процесс неожиданно завершился.
Еще одна причина, по которой может возникнуть это исключение:
Я получаю это исключение в Monitor.Exit, когда после 'await' другой поток продолжает выполнение.
Редактировать: Используйте SemaphoreSlim, потому что он не требует, чтобы поток оставался таким же.
Я нашел проблему. Прежде всего о классе filterCtiCallLog. Я разработал его так, чтобы он работал как асинхронно, так и синхронно. Сначала я написал код для асинхронного выполнения. Мне нужен был способ инициировать события от дочернего рабочего потока к родительскому, чтобы сообщить о рабочем состоянии. Для этого я использовал класс AsyncOperation и его метод post. Вот часть кода для запуска события CtiCallsRetrieved.
Как видите, код выполняется синхронно. Проблема здесь в методе . Я предположил, что если он вызывается в основном потоке, он будет просто запускать событие, а не отправлять его в родительский поток. Однако это было не так. Я не знаю, как это работает, но я изменил код, чтобы проверить, называется ли синхронным или асинхронным. И если это асинхронный вызов, я использовал метод , если нет, я просто активировал , если это не . Вот исправленный код
Всем спасибо за ответы!
Использование флага для попытки отслеживания состояния синхронизирующего объекта ядра просто не сработает - смысл использования этих синхронных вызовов в том, что они работают правильно без какой-либо явной проверки. Установка флагов просто вызовет периодические проблемы, потому что флаг может быть изменен ненадлежащим образом из-за прерываний между проверкой флага и действием на него.
Мьютекс может быть освобожден только угрозой, которая его заполучила. Если обратный вызов вызывается другим потоком (внутренним для CreateFilteredCtiCallLogSync () или пула потоков ядра), выпуск завершится ошибкой.
Непонятно, что именно вы пытаетесь сделать. Предположительно, вы хотите сериализовать доступ к CreateFilteredCtiCallLogSync () и флагам обратного вызова, что экземпляр доступен для повторного использования? В таком случае вы можете использовать семафор - init. его на один блок, дождитесь его в начале и отпустите в обратном вызове.
Есть ли проблема, когда иногда обратный вызов не вызывается, и, следовательно, try / finally / release? В таком случае этот выход кажется немного хитрым, если обратный вызов является асинхронным и может быть вызван другим потоком после того, как поток настройки покинул функцию.
Я видел, как это происходит, когда вы блокируете код с помощью монитора, затем вызываете асинхронный код, и вы получаете это, при использовании блокировки (объекта) вы получаете ошибку компилятора, однако между monitor.enter (объект) и Monitor.Exist (объект ) компилятор не жалуется . к сожалению.
Вы также столкнетесь с этим исключением, если сделаете следующее:
Это потому, что код после ожидания может быть выполнен в другом потоке из строки непосредственно перед ним. По сути, кажется, что если вы асинхронизируете код сейчас (в начале 2020 года), мьютексы просто не работают. Используйте события или что-то в этом роде.
У меня был этот только один или два раза, и в каждом случае это происходило из-за попытки освободить мьютекс, которым я не владел.
Вы уверены, что события возникают в том же потоке, в котором был получен мьютекс? Хотя вы упомянули, что является блокирующим вызовом, возможно, он порождает рабочие потоки, которые вызывают событие?
Читайте также: