目前使QT运行一个实例有三种方式:
1.QSharedMemory
使用共享内存,当第二个进程启动时,判断内存区数据是否建立,如有,则退出; 这种方式有弊端,在程序发生崩溃时,未及时清除共享区数据,导致程序不能正常启动.
2. QtSingleApplication
使用QT扩展库QtSingleApplication,能很好的解决这个问题. 详见: http://qt.nokia.com/products/qt-addons/solutions-archive. 里面就是用的QLocalServer/QLocalSocket建立本地socket来判断实例是否存在
3. 利用QLocalServer实现
MyApplication.h
class MyApplication:public QApplication { Q_OBJECT public: MyApplication(int argc,char **argv); bool isRunning(); private slots: void newLocalConnection(); private: QLocalServer *server; bool _isRunning; };
MyApplication.cpp
MyApplication::MyApplication(int argc, char **argv):QApplication(argc,argv) { _isRunning=false; QCoreApplication::setApplicationName("localserver"); QString serverName=QCoreApplication::applicationName(); QLocalSocket socket; socket.connectToServer(serverName); if(socket.waitForConnected(500)) { QTextStream stream(&socket); QStringList args=QCoreApplication::arguments(); if(args.count()>1) { stream<<args.last(); }else { stream<<QString(); } stream.flush(); qDebug()<<"Connected server,program will quit"; socket.waitForBytesWritten(); /** *qApp->quit(); 此代码是用来退出事件循环的;在构造函数中,事件循环 *尚未启动,因此就无法退出. 最好就是设置标志判断在外部判断 */ _isRunning=true; return; } qDebug()<<"Can't connect to server,build a server"; server=new QLocalServer(this); connect(server,SIGNAL(newConnection()),this,SLOT(newLocalConnection())); if(server->listen(serverName)) { //防止程序崩溃时,残留进程服务,移除之 if(server->serverError()==QAbstractSocket::AddressInUseError&&QFile::exists(server->serverName())) { QFile::remove(server->serverName()); server->listen(serverName); } } } void MyApplication::newLocalConnection() { QLocalSocket *socket=server->nextPendingConnection(); if(!socket) return; socket->waitForReadyRead(1000); //显示传入参数值 QTextStream in(socket); QString vl; in>>vl; qDebug()<<"The value is: "<<vl; delete socket; } bool MyApplication::isRunning() { return _isRunning; }
主程序:
main.cpp
int main(int argc,char **argv) { MyApplication app(argc,argv); if(app.isRunning()) return 0; QLabel label; label.setText("Hello world"); label.show(); return app.exec(); }
第一个实例: