System :: Threading :: Mutex, вызывается из несинхронизированного блока кода. Неожиданный тупик - PullRequest
0 голосов
/ 21 октября 2011

В попытке избавить мой GUI от условий гонки и взаимных блокировок у меня есть следующая функция, которую я вызываю из c'tor, и всякий раз, когда мне нужна служба, которая использует мое именованное имя mutex, чтобы предоставить свой ввод:

void EnvCapt::FireServiceAndOrHold() {
    try {
        mutTimerSyncEx->ReleaseMutex();
        Thread::Sleep(100); //Time enough for the service to complete.
        if (!mutTimerSyncEx->WaitOne(3 * int_ms)) {//int_ms = the polling period
            //Must've been doubly locked or worse.
            mutTimerSyncEx->ReleaseMutex();
            FireServiceAndOrHold();
        }
    } catch (Exception ^ ex) {
        //Released unheld mutex. Retake control.
        mutTimerSyncEx->WaitOne();
        FireServiceAndOrHold();
    }
}

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

Метод синхронизации объектов был вызван из несинхронизированного блока кода.

Потому что, вызывая release для mutex, который не был WaitOne, бросил, я поймал это, зная, что я свободен, чтобы получить право собственности на него и продолжить. Но я не прав. Он навсегда зависает от оператора WaitOne(). Я знаю, что другой процесс делает все это время, потому что он заперт в моем втором окне отладчика. Это не касается мьютекса.

UPDATE

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

  • Это является общим, потому что когда мой GUI c'tor's, то firstInstance ложно, поэтому я пытаюсь взять его под контроль.

  • Это не общий доступ, потому что когда GUI вызывает WaitOne(), GUI блокируется на неопределенный срок. Принимая во внимание, что служба танцует прямо через WaitOne() без заботы в мире.

1 Ответ

3 голосов
/ 21 октября 2011

Я только что понял, что может быть для вас не так:

Подсказка : вы не можете освободить мьютекс от имени другого процесса!Другой процесс должен освободить мьютекс, если он его держит:

Process 1:                           Process 2:
============                         =============

    WaitOne (locks the mutex)

    // do work                       WaitOne (awaits the mutex)

    // do more work

    // done
    ReleaseMutex         ------>     WaitOne returns from the wait _with 
                                             the mutex locked_
...