Qt运行一个实例进程
2015-07-21 18:10
881 查看
一:使用QLocalSocket
方式:首先一个新的实例启动时,将尝试连接到同一个本地服务器,如果连接失败,则表示第一个实例进程,创建一个本地服务器。否则,进行退出。(.pro里加上QT += network)
voidMainWidget::initLocalConnection()
{
is_running = false;
QCoreApplication::setApplicationName("localserver");
QStringserverName = QCoreApplication::applicationName();
QLocalSocket socket;
socket.connectToServer(serverName);
if(socket.waitForConnected(500))
{
is_running =true;
return;
}
//连接不上服务器,就创建一个
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);
}
}
}
voidMainWidget::newLocalConnection()
{
QLocalSocket *socket =server->nextPendingConnection();
if(!socket)
return;
socket->waitForReadyRead(1000);
deletesocket;
}
bool MainWidget::isRunning()
{
returnis_running;
}
main.cpp中:
MainWidget main_widget;
if(!main_widget.isRunning())
{
main_widget.showNormal();
main_widget.raise();
main_widget.activateWindow();
returnapp.exec();
}
1、创建一个QLoaclSocket,连接服务器
2、创建一个QLocalServer,并监听连接
3、启动应用程序之间,检查有多少个连接,如果至少有一个,意味着打开了一个应用程序,则不再打开另一个。
二:使用共享内存
(1)QSharedMemory
方式:先创建一个共享内存,然后在每一个应用程序开始运行之前进行检查是否可以创建一个具有相同unique_id的共享内存,如果不能,则表示创建了实例正在运行。
QSharedMemory shared_memory;
shared_memory.setKey(unique_id);
if(shared_memory.attach())
{
return0;
}
if(shared_memory.create(1))
{
MainWidget main_widget;
main_widget.showNormal();
main_widget.raise();
main_widget.activateWindow();
returnapp.exec();
}
(2)QSystemSemaphore
//确保只运行一次
QSystemSemaphore semaphore("ProgramKey",1, QSystemSemaphore::Open);
semaphore.acquire();
//在临界区操作共享内存SharedMemory
QSharedMemory memory("Program");//全局对象名
if(!memory.create(1)) //如果全局对象存在则提示退出
{
QMessageBox::information(0, "Tip", "Program hasbeen running!");
semaphore.release();
return0;
}
semaphore.release();
三:使用QtSingleApplication
官方发布的有源码,直接下载就可以使用。至于前两种方式在unix下如果程序崩掉内存不释放会出问题。注意QtSingleApplication会在/tmp目录下生成lock文件,若把/tmp变为只读的,就无法运行程序了。
四、网络代码,写一个QSingleApplication类,来实现Qt程序的单例化(参考)
方案一:使用Qt中的QSharedMemory,QLocalServer和QLocalSocket实现(不过需要在你的.pro里加上QT += network)
方案二:使用Qt中的QSharedMemory,和QTimert实现,别的也没翻译,还是直接来代码吧:
使用:
方式:首先一个新的实例启动时,将尝试连接到同一个本地服务器,如果连接失败,则表示第一个实例进程,创建一个本地服务器。否则,进行退出。(.pro里加上QT += network)
voidMainWidget::initLocalConnection()
{
is_running = false;
QCoreApplication::setApplicationName("localserver");
QStringserverName = QCoreApplication::applicationName();
QLocalSocket socket;
socket.connectToServer(serverName);
if(socket.waitForConnected(500))
{
is_running =true;
return;
}
//连接不上服务器,就创建一个
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);
}
}
}
voidMainWidget::newLocalConnection()
{
QLocalSocket *socket =server->nextPendingConnection();
if(!socket)
return;
socket->waitForReadyRead(1000);
deletesocket;
}
bool MainWidget::isRunning()
{
returnis_running;
}
main.cpp中:
MainWidget main_widget;
if(!main_widget.isRunning())
{
main_widget.showNormal();
main_widget.raise();
main_widget.activateWindow();
returnapp.exec();
}
1、创建一个QLoaclSocket,连接服务器
2、创建一个QLocalServer,并监听连接
3、启动应用程序之间,检查有多少个连接,如果至少有一个,意味着打开了一个应用程序,则不再打开另一个。
二:使用共享内存
(1)QSharedMemory
方式:先创建一个共享内存,然后在每一个应用程序开始运行之前进行检查是否可以创建一个具有相同unique_id的共享内存,如果不能,则表示创建了实例正在运行。
QSharedMemory shared_memory;
shared_memory.setKey(unique_id);
if(shared_memory.attach())
{
return0;
}
if(shared_memory.create(1))
{
MainWidget main_widget;
main_widget.showNormal();
main_widget.raise();
main_widget.activateWindow();
returnapp.exec();
}
(2)QSystemSemaphore
//确保只运行一次
QSystemSemaphore semaphore("ProgramKey",1, QSystemSemaphore::Open);
semaphore.acquire();
//在临界区操作共享内存SharedMemory
QSharedMemory memory("Program");//全局对象名
if(!memory.create(1)) //如果全局对象存在则提示退出
{
QMessageBox::information(0, "Tip", "Program hasbeen running!");
semaphore.release();
return0;
}
semaphore.release();
三:使用QtSingleApplication
官方发布的有源码,直接下载就可以使用。至于前两种方式在unix下如果程序崩掉内存不释放会出问题。注意QtSingleApplication会在/tmp目录下生成lock文件,若把/tmp变为只读的,就无法运行程序了。
四、网络代码,写一个QSingleApplication类,来实现Qt程序的单例化(参考)
方案一:使用Qt中的QSharedMemory,QLocalServer和QLocalSocket实现(不过需要在你的.pro里加上QT += network)
// "single_application.h" #ifndef SINGLE_APPLICATION_H #define SINGLE_APPLICATION_H #include <QApplication> #include <QSharedMemory> #include <QLocalServer> class SingleApplication : public QApplication { Q_OBJECT public: SingleApplication(int &argc, char *argv[], const QString uniqueKey); bool isRunning(); bool sendMessage(const QString &message); public slots: void receiveMessage(); signals: void messageAvailable(QString message); private: bool _isRunning; QString _uniqueKey; QSharedMemory sharedMemory; QLocalServer *localServer; static const int timeout = 1000; }; #endif // SINGLE_APPLICATION_H
// "single_application.cpp" #include <QLocalSocket> #include "single_application.h" SingleApplication::SingleApplication(int &argc, char *argv[], const QString uniqueKey) : QApplication(argc, argv), _uniqueKey(uniqueKey) { sharedMemory.setKey(_uniqueKey); if (sharedMemory.attach()) _isRunning = true; else { _isRunning = false; // create shared memory. if (!sharedMemory.create(1)) { qDebug("Unable to create single instance."); return; } // create local server and listen to incomming messages from other instances. localServer = new QLocalServer(this); connect(localServer, SIGNAL(newConnection()), this, SLOT(receiveMessage())); localServer->listen(_uniqueKey); } } // public slots. void SingleApplication::receiveMessage() { QLocalSocket *localSocket = localServer->nextPendingConnection(); if (!localSocket->waitForReadyRead(timeout)) { qDebug(localSocket->errorString().toLatin1()); return; } QByteArray byteArray = localSocket->readAll(); QString message = QString::fromUtf8(byteArray.constData()); emit messageAvailable(message); localSocket->disconnectFromServer(); } // public functions. bool SingleApplication::isRunning() { return _isRunning; } bool SingleApplication::sendMessage(const QString &message) { if (!_isRunning) return false; QLocalSocket localSocket(this); localSocket.connectToServer(_uniqueKey, QIODevice::WriteOnly); if (!localSocket.waitForConnected(timeout)) { qDebug(localSocket.errorString().toLatin1()); return false; } localSocket.write(message.toUtf8()); if (!localSocket.waitForBytesWritten(timeout)) { qDebug(localSocket.errorString().toLatin1()); return false; } localSocket.disconnectFromServer(); return true;
方案二:使用Qt中的QSharedMemory,和QTimert实现,别的也没翻译,还是直接来代码吧:
// "single_application.h" #ifndef SINGLE_APPLICATION_H #define SINGLE_APPLICATION_H #include <QApplication> #include <QSharedMemory> class SingleApplication : public QApplication { Q_OBJECT public: SingleApplication(int &argc, char *argv[], const QString uniqueKey); bool isRunning(); bool sendMessage(const QString &message); public slots: void checkForMessage(); signals: void messageAvailable(QString message); private: bool _isRunning; QSharedMemory sharedMemory; }; #endif // SINGLE_APPLICATION_H
// "single_application.cpp" #include <QTimer> #include <QByteArray> #include "single_application.h" SingleApplication::SingleApplication(int &argc, char *argv[], const QString uniqueKey) : QApplication(argc, argv) { sharedMemory.setKey(uniqueKey); if (sharedMemory.attach()) _isRunning = true; else { _isRunning = false; // attach data to shared memory. QByteArray byteArray("0"); // default value to note that no message is available. if (!sharedMemory.create(byteArray.size())) { qDebug("Unable to create single instance."); return; } sharedMemory.lock(); char *to = (char*)sharedMemory.data(); const char *from = byteArray.data(); memcpy(to, from, qMin(sharedMemory.size(), byteArray.size())); sharedMemory.unlock(); // start checking for messages of other instances. QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(checkForMessage())); timer->start(1000); } } // public slots. void SingleApplication::checkForMessage() { sharedMemory.lock(); QByteArray byteArray = QByteArray((char*)sharedMemory.constData(), sharedMemory.size()); sharedMemory.unlock(); if (byteArray.left(1) == "0") return; byteArray.remove(0, 1); QString message = QString::fromUtf8(byteArray.constData()); emit messageAvailable(message); // remove message from shared memory. byteArray = "0"; sharedMemory.lock(); char *to = (char*)sharedMemory.data(); const char *from = byteArray.data(); memcpy(to, from, qMin(sharedMemory.size(), byteArray.size())); sharedMemory.unlock(); } // public functions. bool SingleApplication::isRunning() { return _isRunning; } bool SingleApplication::sendMessage(const QString &message) { if (!_isRunning) return false; QByteArray byteArray("1"); byteArray.append(message.toUtf8()); byteArray.append('/0'); // < should be as char here, not a string! sharedMemory.lock(); char *to = (char*)sharedMemory.data(); const char *from = byteArray.data(); memcpy(to, from, qMin(sharedMemory.size(), byteArray.size())); sharedMemory.unlock(); return true; }
使用:
// "main.cpp" #include "single_application.h" int main(int argc, char *argv[]) { SingleApplication app(argc, argv, "some unique key string"); if (app.isRunning()) { app.sendMessage("message from other instance."); return 0; } MainWindow *mainWindow = new MainWindow(); // connect message queue to the main window. QObject::connect(&app, SIGNAL(messageAvailable(QString)), mainWindow, SLOT(receiveMessage(QString))); // show mainwindow. mainWindow->show(); return app.exec(); }
相关文章推荐
- Qt中常用的类
- Qt之对话框设计——利用QPalette改变控件颜色
- QT 绘制 局部刷新的N中方法
- QT 的信号与槽机制介绍
- qt实现ssl双向认证服务器
- PyQt的QString 和 QStringList
- qt-vs2010 手动添加新的qt类时,无法生成moc文件的解决
- QTimer的使用
- Qt QLabel::setBuddy函数
- Qt 菜单策略
- Qt数据库:(七)QSqlRelationalTableModel
- Qt资源下载、安装、配置
- QtSpim实现MIPS指令的编写
- Qt的宏
- Qt发布写好的应用程序--动态链接
- 你不知道的21个Qt隐藏功能和技巧
- qt中使用QSplitter分裂器
- Qt数据库:(六)QSqlTableModel
- Qt起步
- 从HelloWorld例子初步认识Qt