一、實(shí)現(xiàn)方案
目前使 Qt 運(yùn)行一個(gè)實(shí)例有如下幾種方式:
1.QSharedMemory
使用共享內(nèi)存,當(dāng)?shù)诙€(gè)進(jìn)程啟動(dòng)時(shí),判斷內(nèi)存區(qū)數(shù)據(jù)是否建立,如有,則退出;這種方式有弊端,在程序發(fā)生崩潰時(shí),未及時(shí)清除共享區(qū)數(shù)據(jù),導(dǎo)致程序不能正常啟動(dòng)。
2.文件鎖
在程序運(yùn)行的時(shí)候就在目錄下創(chuàng)建一個(gè)文件,當(dāng)程序運(yùn)行時(shí)就判斷這個(gè)文件是否存在,如果存在說(shuō)明程序已經(jīng)在運(yùn)行。其本質(zhì)與 QSharedMemory 相同。
3.利用QLocalServer
使Qt應(yīng)用程序能夠單實(shí)例運(yùn)行的典型實(shí)現(xiàn)方法是使用共享內(nèi)存實(shí)現(xiàn)。該方法實(shí)現(xiàn)簡(jiǎn)單,代碼簡(jiǎn)潔。
但有一個(gè)致命缺陷:共享內(nèi)存(QSharedMemory)實(shí)現(xiàn)的單程序運(yùn)行,當(dāng)運(yùn)行環(huán)境是UNIX時(shí),并且程序不幸崩潰,會(huì)導(dǎo)致共享內(nèi)存無(wú)法釋放,從而無(wú)法重新運(yùn)行程序!
4.QtSingleApplication
使用 Qt 擴(kuò)展庫(kù) QtSingleApplication,能很好的解決這個(gè)問(wèn)題。
QSingleApplication 是 Qt 提供的一個(gè) solution ,它不包含在 Qt 的 library 中。遵循 LGPL 協(xié)議。Qt 歡迎里面有例子。
二、實(shí)現(xiàn)代碼
下面給出了 LocalServer 方式的實(shí)現(xiàn)代碼。
SingleApplication.h:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-497979.html
#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H
#include <QObject>
#include <QApplication>
#include <QtNetwork/QLocalServer>
#include <QWidget>
class SingleApplication : public QApplication {
Q_OBJECT
public:
SingleApplication(int &argc, char **argv);
bool isRunning(); // 是否已經(jīng)有實(shí)例在運(yùn)行
QWidget *w; // MainWindow指針
private slots:
// 有新連接時(shí)觸發(fā)
void _newLocalConnection();
private:
// 初始化本地連接
void _initLocalConnection();
// 創(chuàng)建服務(wù)端
void _newLocalServer();
// 激活窗口
void _activateWindow();
bool _isRunning; // 是否已經(jīng)有實(shí)例在運(yùn)行
QLocalServer *_localServer; // 本地socket Server
QString _serverName; // 服務(wù)名稱(chēng)
};
#endif // SINGLEAPPLICATION_H
SingleApplication.cpp:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-497979.html
#include "SingleApplication.h"
#include <QtNetwork/QLocalSocket>
#include <QFileInfo>
#define TIME_OUT (500) // 500ms
SingleApplication::SingleApplication(int &argc, char **argv)
: QApplication(argc, argv)
, w(NULL)
, _isRunning(false)
, _localServer(NULL) {
// 取應(yīng)用程序名作為L(zhǎng)ocalServer的名字
_serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
_initLocalConnection();
}
// 說(shuō)明:
// 檢查是否已經(jīng)有一個(gè)實(shí)例在運(yùn)行, true - 有實(shí)例運(yùn)行, false - 沒(méi)有實(shí)例運(yùn)行
bool SingleApplication::isRunning() {
return _isRunning;
}
// 說(shuō)明:
// 通過(guò)socket通訊實(shí)現(xiàn)程序單實(shí)例運(yùn)行,監(jiān)聽(tīng)到新的連接時(shí)觸發(fā)該函數(shù)
void SingleApplication::_newLocalConnection() {
QLocalSocket *socket = _localServer->nextPendingConnection();
if(socket) {
socket->waitForReadyRead(2*TIME_OUT);
delete socket;
// 其他處理,如:讀取啟動(dòng)參數(shù)
_activateWindow();
}
}
// 說(shuō)明:
// 通過(guò)socket通訊實(shí)現(xiàn)程序單實(shí)例運(yùn)行,
// 初始化本地連接,如果連接不上server,則創(chuàng)建,否則退出
void SingleApplication::_initLocalConnection() {
_isRunning = false;
QLocalSocket socket;
socket.connectToServer(_serverName);
if(socket.waitForConnected(TIME_OUT)) {
fprintf(stderr, "%s already running.\n",
_serverName.toLocal8Bit().constData());
_isRunning = true;
// 其他處理,如:將啟動(dòng)參數(shù)發(fā)送到服務(wù)端
return;
}
//連接不上服務(wù)器,就創(chuàng)建一個(gè)
_newLocalServer();
}
// 說(shuō)明:
// 創(chuàng)建LocalServer
void SingleApplication::_newLocalServer() {
_localServer = new QLocalServer(this);
connect(_localServer, SIGNAL(newConnection()), this, SLOT(_newLocalConnection()));
if(!_localServer->listen(_serverName)) {
// 此時(shí)監(jiān)聽(tīng)失敗,可能是程序崩潰時(shí),殘留進(jìn)程服務(wù)導(dǎo)致的,移除之
if(_localServer->serverError() == QAbstractSocket::AddressInUseError) {
QLocalServer::removeServer(_serverName); // <-- 重點(diǎn)
_localServer->listen(_serverName); // 再次監(jiān)聽(tīng)
}
}
}
// 說(shuō)明:
// 激活主窗口
void SingleApplication::_activateWindow() {
if(w) {
w->show();
w->raise();
w->activateWindow(); // 激活窗口
}
}
調(diào)用示例:
#include "MainWindow.h"
#include "SingleApplication.h"
int main(int argc, char *argv[]) {
SingleApplication a(argc, argv);
if(!a.isRunning()) {
MainWindow w;
a.w = &w;
w.show();
return a.exec();
}
return 0;
}
到了這里,關(guān)于Qt 實(shí)現(xiàn)應(yīng)用程序單實(shí)例的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!