[Columna Qt] Varias formas de implementar programas singleton y prohibir la apertura de múltiples programas

Tabla de contenido

1. Breve introducción

2. Ejemplo de implementación (Windows)

1. Utilice un mecanismo de exclusión mutua a nivel del sistema

2. A través de memoria compartida (comunicación entre procesos-IPC)

3. Utilice bloqueos mutex con nombre (no recomendado)

4. Utilice el bloqueo de archivos

5. Detección a través del puerto de red


1. Breve introducción

Prefacio

  • Prohibir múltiples aplicaciones, también conocida como "aplicación de instancia única" o "aplicación de instancia única", se refiere a evitar que se ejecuten múltiples instancias de la misma aplicación al mismo tiempo a través de diversos medios. Este enfoque mejora la estabilidad de las aplicaciones, la eficiencia en la utilización de recursos y la experiencia del usuario.

Objetivo

  • El objetivo principal de prohibir múltiples aplicaciones es garantizar que solo se pueda ejecutar una instancia de la aplicación al mismo tiempo para evitar el desperdicio de recursos, conflictos de datos, confusión y otros problemas, a fin de mejorar la calidad de la aplicación y la satisfacción del usuario.

beneficio

  1. Gestión de recursos: ejecutar varias instancias al mismo tiempo puede provocar un desperdicio de recursos, como memoria, uso de CPU, etc. Al limitarse a una instancia en ejecución, los recursos del sistema se pueden administrar de manera más eficiente.
  2. Coherencia de los datos: si la aplicación implica modificaciones en los datos o el estado compartidos, varias instancias que se ejecutan al mismo tiempo pueden causar inconsistencia en los datos. Esto se puede evitar desactivando la apertura múltiple.
  3. Reducir los conflictos: varias instancias pueden intentar acceder a los mismos recursos, como archivos, bases de datos, etc., lo que genera conflictos y errores. Prohibir múltiples aperturas puede reducir la ocurrencia de esta situación.
  4. Evite la ofuscación: si su aplicación depende de hardware específico o dispositivos externos, varias instancias pueden causar ofuscación o contención del dispositivo, impidiendo que la funcionalidad funcione correctamente.
  5. Mejore la experiencia del usuario: cuando los usuarios solo esperan ejecutar una instancia, abrir varias instancias puede confundirlos. Al prohibir múltiples aperturas, se puede mejorar la experiencia del usuario y la facilidad de uso.

Método para realizar

  1. Mecanismo de exclusión mutua a nivel del sistema: utilice el mecanismo de exclusión mutua proporcionado por el sistema operativo, como mutex con nombre, etc.
  2. Memoria compartida o canalizaciones con nombre: utilice memoria compartida o canalizaciones con nombre para comunicarse entre diferentes instancias y evitar múltiples instancias.
  3. Mutex con nombre o bloqueo de archivo: cree un mutex o bloqueo de archivo con un nombre único. Si ya existe, significa que ya hay una instancia ejecutándose.
  4. Detección de puerto de red: intente vincularse a un puerto de red específico. Si el enlace se realiza correctamente, significa que no hay otras instancias en ejecución.
  5. Detección de variables de entorno: verifique la variable de entorno, si está configurada, significa que ya se está ejecutando una instancia.

Resumir

  • En resumen, prohibir múltiples aperturas de programas es una forma de optimizar las aplicaciones y garantizar que se ejecuten de manera estable y eficiente en diferentes entornos. La elección de la implementación adecuada depende de las necesidades de su aplicación y de la tecnología.

2. Ejemplo de implementación (Windows)

1. Utilice un mecanismo de exclusión mutua a nivel del sistema

  • Algunos sistemas operativos proporcionan un mecanismo mutex a nivel de sistema que evita que se ejecuten varias instancias de la misma aplicación. Por ejemplo, Windows proporciona exclusiones mutuas con nombre para lograr esto.
  • Plantilla de muestra
  • Código de muestra
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <Windows.h>

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

    // L"字符串":表示将ANSI字符串转换成unicode的字符串,使每个字符占两个字节
    HANDLE hMutex = CreateMutex(nullptr, TRUE, (LPCWSTR)qApp->applicationName().toStdWString().c_str());
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");
        CloseHandle(hMutex);
        hMutex = NULL;
        return 1;
    }

    // 在此处写你的应用程序逻辑代码
    MainWindow w;
    w.show();
    a.exec();

    // 完成后关闭互斥锁
    CloseHandle(hMutex);
    hMutex = NULL;
    return 0;
}

2. A través de memoria compartida (comunicación entre procesos-IPC)

  • Utilice técnicas de comunicación entre procesos, como la memoria compartida, para detectar si una instancia ya se está ejecutando.
  • Plantilla de muestra (usando QSharedMemory de Qt para la comunicación entre procesos )
  • Código de muestra
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <QSharedMemory>

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

    QSharedMemory sharedMemory(qApp->applicationName());    // 设置绑定的共享内存段的key值
    if(sharedMemory.attach()){
        QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");
        return 1;
    }else{
        sharedMemory.create(1); // 创建1byte大小的共享内存段
    }

    // 在此处写你的应用程序逻辑代码
    MainWindow w;
    w.show();
    a.exec();

    // 完成后分离共享内存
    sharedMemory.detach();
    return 0;
}

3. Utilice bloqueos mutex con nombre (no recomendado)

  • Cree un mutex con nombre cuando se inicie la aplicación, asegurándose de que solo una instancia pueda adquirir el bloqueo y otras instancias serán bloqueadas.
  • Plantilla de muestra
  • Código de muestra
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <QSystemSemaphore>

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

    // 声明一个命名互斥锁,用于防止多开
    QSystemSemaphore semaphore(qApp->applicationName(), 1, QSystemSemaphore::Open);

    if (!semaphore.acquire()) {
        QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");
        return 1;
    }

    // 在此处写你的应用程序逻辑代码
    MainWindow w;
    w.show();
    a.exec();

    // 释放互斥锁,允许其他实例运行
    semaphore.release();
    return 0;
}

4. Utilice el bloqueo de archivos

  • Se crea un bloqueo de archivo específico cuando se inicia la aplicación. Si el bloqueo ya existe, significa que ya hay una instancia ejecutándose.
  • Plantilla de muestra
  • Código de muestra
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <QFile>

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

    QFile lockFile(qAppName() +".lock");
    if (lockFile.exists()) {
        QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");
        return 1;
    }

    lockFile.open(QIODevice::WriteOnly);
    lockFile.write("Running"); // 向锁文件写入一些数据
    lockFile.close();

    // 在此处写你的应用程序逻辑代码
    MainWindow w;
    w.show();
    a.exec();

    // 完成后删除锁定文件
    lockFile.remove();
    return 0;
}

5. Detección a través del puerto de red

  • Intenta vincularse a un puerto de red específico cuando se inicia la aplicación; si el enlace se realiza correctamente, significa que no hay otras instancias en ejecución.
  • Plantilla de muestra
  • Código de muestra
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include <QTcpServer>

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

    QTcpServer tcpServer;
    if (!tcpServer.listen(QHostAddress::LocalHost, 12345)) {
        QMessageBox::warning(nullptr, "Error", "An instance of the application is already running.");
        return 1;
    }

    // 在此处写你的应用程序逻辑代码
    MainWindow w;
    w.show();
    a.exec();

    // 完成后关闭服务器
    tcpServer.close();
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_43729127/article/details/132492041
Recomendado
Clasificación