2014-08-27 4 views
-1

Резюме:Как я могу избавиться от заброшенных мьютексов?

Есть ли способ, чтобы очистить мьютекс, если процесс, который создал его умер и ушел?

Детали:

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

При тестировании какого-либо нового кода (для автоматического обновления) я запускал Environment.Exit (0). Во время работы в режиме отладки мой мьютекс был очищен.

Но когда я изменил сборку, чтобы быть «Release», то мьютекс остается вокруг после вызова выхода и помечается как покинутый:

Abandoned Mutex

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

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

Я попытался освободить мьютекс так:

bool createdNew; 
string applicationId = "18773:TestStudio"; 
var singleInstanceMutex = new Mutex(true, applicationId, out createdNew); 

singleInstanceMutex.Close(); // Tried ReleaseMutex() too 

но, конечно, просто получает его, а затем освобождает его.

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

Есть ли способ очистить мьютекс, если процесс, который его создал, мертв и ушел?

+3

Согласно вашему снимку экрана 3 вещи все еще ссылаются на него. Закройте все, что еще есть. –

+0

@Scott Chamberlain - Ссылка остается, но процесс давно ушел. Он умер таким образом, что не освобождает ссылку. Отсюда мой вопрос о том, как высвободить мьютекс. – Vaccano

+0

@ Vccano, тогда у вас есть одна из двух ситуаций. Коррумпированная установка ОС, или что-то имеет ссылку, которую вы не понимаете, берет ссылку. Если он действительно исчез, то счет будет равен 0, очистка дескрипторов от неудачных процессов была исправлена ​​в Windows 95 (или 98, я не могу вспомнить, какие). Вероятная ситуация заключается либо в том, что программа еще не мертва, а что-то еще сохраняет ее, когда вы думаете, что она мертва или какая-то другая программа (IIS, антивирус, кто знает) подбирает ручку и не отпускает ее. –

ответ

0

Не знаю, если это на самом деле отвечает на ваш вопрос, но вот код я использую для этой цели:

// Mutex object used to determine if there are multiple instances of this program running. 
    // Note that this is a reference to a .Net Mutex object, not the Windows mutex itself. 
    private static Mutex _onlyOneInstanceMutex; 



    /// <summary> 
    /// Method to test that there is not another instance of the program already running on this 
    /// machine, or at least in this Terminal Services session or Windows Vista/Windows 7 
    /// concurrent sessions session. If there is, a message box-style localized error message is 
    /// displayed and the value false is returned. This implies that this method should not be 
    /// used in programs that are run as a Windows service. 
    /// 
    /// This implementation uses a .Net Mutex object in public storage to prevent it from being 
    /// garbage-collected. The name of the associated Windows mutex is simply the program name as 
    /// provided by the caller. Neither the .Net Mutex object nor the Windows mutex are ever 
    /// explicitly released; they remain in existence, perhaps in an "abandoned" state, until the 
    /// process that created them terminates. 
    /// </summary> 
    /// <returns>false if another instance running, otherwise true</returns> 
    [SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive", 
        Justification = "Not sure if this is correct or not.")] 
    public static bool TestOnlyOneInstance(string programName) 
    { 
    // Funny construct to prevent the Mutex from being garbage collected 
    GC.KeepAlive(_onlyOneInstanceMutex); 

    // Test if we are the first instance, and if so create the Windows mutex, making it 
    // impossible for subsequent instances to successfully create their mutex 
    bool firstInstance; 
    _onlyOneInstanceMutex = new Mutex(false, programName, out firstInstance); 
    if (firstInstance) 
     return true; 

    // Display a (possibly localized) error message, then return 
    string errorMessage = MLocalizer.GetString("Error1", 
      "Another instance of this program is already running on this machine.") + 
     "\n" + MLocalizer.GetString("Error2", 
            "You cannot run two instances at the same time.") + 
     "\n" + MLocalizer.GetString("Error3", "Please use the other instance."); 
    MessageBox.Show(errorMessage, programName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
    return false; 
    } 

EDIT:

только различия можно увидеть в моем коде и у вас что я указываю «изначально принадлежащий» как ложный, и у меня есть забавная вещь о сборке мусора.

О, и я объявляю статику Mutex.