Evgenii Legotckoi
Evgenii LegotckoiҚаң. 28, 2016, 11:11 Т.Ж.

Qt/C++ - сабақ 043. Qt Single Application - тек бір қолданба данасын іске қосыңыз

Тек бір қолданба данасын іске қосуға рұқсат беру жадтың ағып кетуіне қатысты мәселелерді шектеу немесе бірдей ресурстар, файлдар, SQLite дерекқоры және т.б. үшін бәсекелес екі қолданба даналарымен ықтимал ақауларды жою үшін қажет болуы мүмкін. Немесе қолданба, негізінен, пайдаланушы пайдаланатын бір ғана дананы қабылдайтын болса.

Бұл мәселені шешу үшін келесі екі әдісті қолдануға болады:

  • QLockFile пайдалану - қолданба жабылған кезде жойылатын уақытша файл жасалғанда. Бұл ретте қосымшаның екінші данасы іске қосылған кезде осы файлдың бар-жоғына тексеру жүргізіледі және егер файл қолданбаның бір ашық данасы арқылы жасалған болса, онда екінші данасы автоматты түрде жабылады;
  • QSystemSemaphore және QSharedMemory пайдалану - бұл жағдайда ортақ жад сегменті жасалады және оны бірегей идентификатор арқылы бар сегментке қосу әрекеті жасалады. Тіркеме әрекеті сәтті болса, бір қолданба данасы әлдеқашан жасалған. Тиісінше, біз бұл туралы пайдаланушыға хабарлаймыз және қолданбаны жабамыз. Тіркеу әрекеті сәтсіз болса, біз қолданба үшін жад сегментін жасаймыз және бірінші дананы іске қосамыз.

Бағдарламаның барлық келесі коды main.cpp шегінен шықпайды.

QLockFile қолданатын жалғыз қолданба

Төмендегі кодта қолданба іске қосылған кезде уақытша файлдар қалтасында Lock File жасалады; Lock File құру әрекеті сәтсіз болған жағдайда, бағдарлама қолданбаның бір данасы деп есептейді. әлдеқашан ашық, ол туралы пайдаланушыға хабарлайды және жабылады.

Ескерту. Ауыстыру жеке куәлігіңізге.

#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();
}

QSystemSemaphore және QSharedMemory көмегімен жалғыз қолданба

Бірінші нұсқа Qt қолданбасының іске қосылған даналарының санын шектеу мәселесінің қарапайым және ыңғайлы шешімін береді. Бірақ QLockFile шешімінің кемшіліктері де бар, себебі пайдаланушы үшін рұқсат мәселелері болуы мүмкін. Сондай-ақ, бағдарламаны бүкіл компьютерде бір данада іске қосуды шектегіңіз келсе, онда қанша пайдаланушы сеансы іске қосылатынына қарамастан, QLockFile пайдалану да бұл мүмкіндікті қамтамасыз етпейді.

QSharedMemory , керісінше, компьютерде бір уақытта жұмыс істейтін барлық пайдаланушыларға ортақ. Сондықтан, егер пайдаланушылардың бірі сіздің бағдарламаңызды іске қосса, екіншісі оны енді іске қоса алмайды.

Бірақ бұл жағдайда әртүрлі платформаларда ортақ жадпен жұмыс істеудегі айырмашылықтар туралы ұмытпау керек. Windows, жағдайында ортақ жад бағдарламаның қалыпты аяқталуы кезінде де, әдеттен тыс аяқталғанда да босатылады. Linux/Unix жағдайында, бұзылған кезде жад босатылмайды.

Төмендегі кодта бір қолданбаның бірнеше даналары бір уақытта іске қосылған кезде жарыс шартын шешу үшін семафор пайдаланылады. Семафор есептегішпен жасалады, оның ең көп саны 1. Семафор көтерілген кезде қолданбаның барлық басқа даналары ортақ жадқа енді қатынаса алмайды және сәйкесінше бір данасы ресурстарға толық иелік етеді. Бұл дана қолданбаға сәйкес идентификаторы бар ортақ жад сегментінің болуы арқылы іске қосылған қолданбаның басқа данасын тексереді. Дана сәтті басталады және басқа қолданба данасы туралы ақпаратты таппаған жағдайда ортақ жад сегментін жасайды. Содан кейін семафор жойылып, қолданбаның басқа даналарына бастауға әрекет жасауға мүмкіндік береді.

Ескерту. Ауыстыру Және жеке куәлігіңізге.

#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();
}

Бейне оқулық

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

IscanderChe
  • Қар. 25, 2018, 3:49 Т.Ж.

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

Evgenii Legotckoi
  • Қар. 25, 2018, 12:20 Т.Қ.

Добрый день!

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

IscanderChe
  • Қар. 25, 2018, 1:24 Т.Қ.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз