前言
在项目中,会遇到这么一个需求,应用程序只能存在一个运行实例。关于这需求,网上流行几种实现方式:
- 通过QSharedMemory实现
- 使用官方提供的QTSingleApplication
- 使用QLocalServer和QLocalSocket
本文章主要介绍第三种方式
实现思路
- 继承QApplicaiton或者QCoreApplication自定义一个SingleApplication
- 在SingleApplication构造函数中创建一个QLocalSocket连接指定server_name的server,这时有两种情况:
2.1 假如没有连接成功,则代表没有运行实例,这时允许程序运行,并创建一个指定server_name的QLocalServer用来监听连接
2.2 假如连接成功,从第二步可以发现,这时已经存在了一个运行实例,这时就不允许再创建新的运行实例
具体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| SingleApplication::SingleApplication(int &argc, char **argv) : QApplication(argc, argv) { m_serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName(); initServer(); }
void SingleApplication::onNewConnection() { QLocalSocket *socket = m_server->nextPendingConnection(); if (socket) { socket->waitForReadyRead(1000); delete socket; } }
void SingleApplication::initServer() { QLocalSocket socket;
// 连接以应用程序名称为server name的server // 如果连接不上则代表未启动,此时创建一个新的server m_isRunning = false; socket.connectToServer(m_serverName); if (socket.waitForConnected()) { m_isRunning = true; return; }
m_server = new QLocalServer(this); connect(m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection())); if (!m_server->listen(m_serverName)) { // 此时监听失败,可能是程序崩溃是残留进程的服务所导致,移除之 if (QAbstractSocket::AddressInUseError == m_server->serverError()) { QLocalServer::removeServer(m_serverName); m_server->listen(m_serverName); } } }
|