Evgenii Legotckoi
Evgenii Legotckoi28. Januar 2016 11:11

Qt/C++ - Lektion 043. Qt Single Application - Nur eine Anwendungsinstanz starten

Das Ausführen nur einer Anwendungsinstanz kann erforderlich sein, um Probleme mit Speicherlecks zu begrenzen oder um mögliche Probleme mit zwei Anwendungsinstanzen zu beseitigen, die um dieselben Ressourcen, Dateien, SQLite-Datenbank usw. konkurrieren. Oder wenn die Anwendung im Prinzip nur eine vom Benutzer verwendete Instanz annimmt.

Um dieses Problem zu lösen, können Sie die folgenden zwei Methoden verwenden:

  • Verwenden von QLockFile - wenn eine temporäre Datei erstellt wird, die beim Schließen der Anwendung zerstört wird. Gleichzeitig wird beim Start der zweiten Instanz der Anwendung geprüft, ob diese Datei existiert, und wenn die Datei bereits von einer geöffneten Instanz der Anwendung erstellt wurde, wird die zweite Instanz automatisch geschlossen;
  • Verwendung von QSystemSemaphore und QSharedMemory - in diesem Fall wird ein gemeinsam genutztes Speichersegment erstellt und versucht, es durch eine eindeutige Kennung an ein vorhandenes Segment anzuhängen. Wenn der Verbindungsversuch erfolgreich ist, wurde bereits eine Anwendungsinstanz erstellt. Dementsprechend weisen wir den Nutzer darauf hin und schließen die Anwendung. Wenn der Verbindungsversuch nicht erfolgreich war, erstellen wir ein Speichersegment für die Anwendung und starten die erste Instanz.

Alle weiteren Programmcodes gehen nicht über main.cpp hinaus.

Einzelne Anwendung mit QLockFile

Im folgenden Code wird eine Sperrdatei im Ordner für temporäre Dateien erstellt, wenn die Anwendung gestartet wird;

Notiz. Ersetzen zu Ihrem Ausweis.

#include "widget.h"
#include <QApplication>
#include <QLockFile>
#include <QDir>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QLockFile lockFile(QDir::temp().absoluteFilePath("lurity.lock"));

    /* Пытаемся закрыть Lock File, если попытка безуспешна в течение 100 миллисекунд,
     * значит уже существует Lock File созданный другим процессом.
     * Следовательно, выбрасываем предупреждение и закрываем программу
     * */
    if (!lockFile.tryLock(100))
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setText("Приложение уже запущено.\n"
                       "Разрешено запускать только один экземпляр приложения.");
        msgBox.exec();
        return 1;
    }

    Widget w;
    w.show();

    return a.exec();
}

Einzelanwendung mit QSystemSemaphore und QSharedMemory

Die erste Option bietet eine einfache und bequeme Lösung für das Problem, die Anzahl der ausgeführten Instanzen einer Qt -Anwendung zu begrenzen. Die QLockFile -Lösung hat jedoch auch Nachteile, da es möglicherweise zu Berechtigungsproblemen für den Benutzer kommt. Wenn Sie das Programm auf die Ausführung in einer Instanz auf dem gesamten Computer beschränken möchten, unabhängig davon, wie viele Benutzersitzungen darauf ausgeführt werden können, bietet die Verwendung von QLockFile diese Funktion ebenfalls nicht.

QSharedMemory hingegen wird von allen Benutzern gemeinsam genutzt, die gleichzeitig am Computer arbeiten. Wenn also einer der Benutzer Ihr Programm gestartet hat, kann der zweite es nicht mehr ausführen.

Aber in diesem Fall sollten Sie die Unterschiede beim Arbeiten mit Shared Memory auf verschiedenen Plattformen nicht vergessen. Im Fall von Windows wird gemeinsam genutzter Speicher sowohl bei normaler Programmbeendigung als auch bei abnormaler Beendigung freigegeben. Bei Linux/Unix wird der Speicher beim Absturz nicht freigegeben.

Im folgenden Code wird ein Semaphor verwendet, um die Racebedingung aufzulösen, wenn mehrere Instanzen derselben Anwendung gleichzeitig ausgeführt werden. Das Semaphor wird mit einem Zähler erstellt, dessen maximale Anzahl 1 ist. Wenn das Semaphor ausgelöst wird, haben alle anderen Instanzen der Anwendung keinen Zugriff mehr auf den gemeinsamen Speicher und dementsprechend besitzt eine Instanz die Ressourcen vollständig. Diese Instanz sucht nach einer anderen Instanz der Anwendung, die ausgeführt wird, indem ein gemeinsames Speichersegment mit einer ID vorhanden ist, die mit der Anwendung übereinstimmt. Die Instanz startet erfolgreich und erstellt ein gemeinsames Speichersegment, falls sie keine Informationen zu einer anderen Anwendungsinstanz gefunden hat. Das Semaphor wird dann gelöscht, wodurch andere Instanzen der Anwendung versuchen können, zu starten.

Notiz. Ersetzen und zu Ihrem Ausweis.

#include "mainwindow.h"
#include <QApplication>
#include <QSystemSemaphore>
#include <QSharedMemory>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSystemSemaphore semaphore("<uniq id>", 1);  // создаём семафор
    semaphore.acquire(); // Поднимаем семафор, запрещая другим экземплярам работать с разделяемой памятью

#ifndef Q_OS_WIN32
    // в linux/unix разделяемая память не освобождается при аварийном завершении приложения,
    // поэтому необходимо избавиться от данного мусора
    QSharedMemory nix_fix_shared_memory("<uniq id 2>");
    if (nix_fix_shared_memory.attach())
    {
        nix_fix_shared_memory.detach();
    }
#endif

    QSharedMemory sharedMemory("<uniq id 2>");  // Создаём экземпляр разделяемой памяти
    bool is_running;            // переменную для проверки ууже запущенного приложения
    if (sharedMemory.attach())
    {                           // пытаемся присоединить экземпляр разделяемой памяти
                                // к уже существующему сегменту
        is_running = true;      // Если успешно, то определяем, что уже есть запущенный экземпляр
    } 
    else
    {
        sharedMemory.create(1); // В противном случае выделяем 1 байт памяти
        is_running = false;     // И определяем, что других экземпляров не запущено
    }
    semaphore.release();        // Опускаем семафор

    // Если уже запущен один экземпляр приложения, то сообщаем об этом пользователю
    // и завершаем работу текущего экземпляра приложения
    if (is_running)
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setText(QObject::trUtf8("Приложение уже запущено.\n"
                        "Вы можете запустить только один экземпляр приложения."));
        msgBox.exec();
        return 1;
    }

    MainWindow w;
    w.show();

    return a.exec();
}

Videoanleitung

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

IscanderChe
  • 25. November 2018 03:49

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

Evgenii Legotckoi
  • 25. November 2018 12:20

Добрый день!

С помощью API целевой системы придётся найти нужный процесс и открыть окно. Но придётся писать платформозависимый код. В случае Windows нужно смотреть, как с помощью WinAPI искать процессы и пытаться открыть их окна, если они есть. В случае Linux там ещё сложнее, или через XLib, или через DBus, но я не уверен, как именно это делается.

IscanderChe
  • 25. November 2018 13:24

Понятно. Спасибо!

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
A
ALO1ZE19. Oktober 2024 08:19
Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken