В OnStartup:
bool existed;
string guid = Marshal.GetTypeLibGuidForAssembly(Assembly.GetExecutingAssembly()).ToString();
Mutex mutexObj = new Mutex(true, guid, out existed);
if(existed)
...
Код честно скопирован отсюда.
Все должно работать, однако, самое интересное начаниется при попытке вывести Mutex в другой метод:
private static bool IsNotOpenAlready() {
bool existed;
string guid = Marshal.GetTypeLibGuidForAssembly(Assembly.GetExecutingAssembly()).ToString();
Mutex mutexObj = new Mutex(true, guid, out existed);
return existed;
}
Вызывается метод в app.xaml:
if(IsNotOpenAlready())
...
Он всегда выдает true, вне зависимости, открыт второй экземпляр, нет. Однако, если оставить Mutex в OnStartup все работает. Почему?
Если вы в, например, WPF приложении в OnStartup создаете просто локальную переменную мьютекса, то после того, как метод будет выполнен, переменная и сам мьютекс будут уничтожены сборщиком.
Чтобы такого не происходило, надо держать ссылку на мьютекс, например, в поле класса или в статическом поле.
UPD
Говоря об оптимизаторе и GC и почему в одном случае объект был уничтожен сразу, а в другом не сразу, вспоминается известный пример с таймером.
Возьмем от этот код
void Main()
{
var timer = new Timer(Callback, null, 0, 5);
Thread.Sleep(3000);
}
private static void Callback(object state)
{
string.Format("Called at {0}", DateTime.Now).Dump();
GC.Collect();
}
И запустим его без оптимизатора
Мы видим много много вызвов таймера. А теперь просто включаем оптимизатор
И видим, что вызвов таймера всего ничего. Почему? Потому что оптимизатор видит, что таймер не используется после Thread.Sleep(3000) и советует GC его удалить (как он это делает я не помню, если честно. Нверное удаляет из корней, по которым строится граф ссылок для GC). Но стоит как то использовать переменную после Thread.Sleep(3000)
то всё снова становится хорошо. Отсюда можно понять, зачем нужен метод GC.KeepAlive и почему от так реализован.
Продвижение своими сайтами как стратегия роста и независимости