IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> QT 实现程序单例的几种方式 -> 正文阅读

[C++知识库]QT 实现程序单例的几种方式

所谓程序单例,也就是在电脑上只允许一个程序只有一个实例在运行。

在QT环境中,实现程序单例的方法一般是这样的:程序启动的时候,先判断指定了key的共享内存是否可以attach,如果可以,则证明已经有一个实例在运行,否则就创建一块共享内存。

AppSingleton

实现逻辑:创建一块共享内存,启动定时器检查共享内存的数据,来判断是否有新的信号进来。

app_singleton.h
#pragma once
#include <QApplication>
#include <QSharedMemory>

class AppSingleton : public QApplication
{
	Q_OBJECT
public:
	AppSingleton(int& argc, char* argv[], const QString uniqueKey);
	bool isRunning();
	bool sendMessage(const QString& message);

signals:
	void signalMessageAvailable(QString message);

public slots:
	void checkForMessage();

private:
	bool is_running_;
	QSharedMemory shared_memory_;
};

app_singleton.cpp
#include "app_singleton.h"
#include <QTimer>
#include <QByteArray>


AppSingleton::AppSingleton(int& argc, char* argv[], const QString uniqueKey) 
	: QApplication(argc, argv)
{
	shared_memory_.setKey(uniqueKey);
	if (shared_memory_.attach())
	{
		is_running_ = true;
	}
	else
	{
		is_running_ = false;
		// attach data to shared memory.
		QByteArray byteArray("0"); // default value to note that no message is available.
		if (!shared_memory_.create(byteArray.size()))
		{
			qDebug("Unable to create single instance.");
			return;
		}
		shared_memory_.lock();
		char* to = (char*)shared_memory_.data();
		const char* from = byteArray.data();
		memcpy(to, from, qMin(shared_memory_.size(), byteArray.size()));
		shared_memory_.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 AppSingleton::checkForMessage()
{
	shared_memory_.lock();
	QByteArray byteArray = QByteArray((char*)shared_memory_.constData(), shared_memory_.size());
	shared_memory_.unlock();

	if (byteArray.left(1) == "0")
		return;

	byteArray.remove(0, 1);
	QString message = QString::fromUtf8(byteArray.constData());
	emit signalMessageAvailable(message);

	// remove message from shared memory.
	byteArray = "0";
	shared_memory_.lock();
	char* to = (char*)shared_memory_.data();
	const char* from = byteArray.data();
	memcpy(to, from, qMin(shared_memory_.size(), byteArray.size()));
	shared_memory_.unlock();
}

// public functions.
bool AppSingleton::isRunning()
{
	return is_running_;
}

bool AppSingleton::sendMessage(const QString& message)
{
	if (!is_running_)
		return false;

	QByteArray byteArray("1");
	byteArray.append(message.toUtf8());
	byteArray.append('\0'); 

	shared_memory_.lock();
	char* to = (char*)shared_memory_.data();
	const char* from = byteArray.data();
	memcpy(to, from, qMin(shared_memory_.size(), byteArray.size()));
	shared_memory_.unlock();

	return true;
}

SingleApplication

实现逻辑:创建一块共享内存和QLocalServer,监听是否有新的连接进来。

single_application.h
/*!
 * \file SingleApplication.h
 *
 * \author Kandy
 * \date 2022/3/17 15:21:16
 *
 * \brief 程序单例
 */
#pragma once
#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);

signals:
	void signalMessageAvailable(QString message);

public slots:
	void onNewConnection();

private:
	bool is_running_;
	QString unique_key_;
	QSharedMemory shared_memory_;
	QLocalServer* local_server_;
	static const int timeout_ = 1000;
};
single_application.cpp
#include "single_application.h"
#include <QLocalSocket>
#pragma execution_character_set("utf-8")

SingleApplication::SingleApplication(int& argc, char* argv[], const QString uniqueKey) 
	: QApplication(argc, argv)
	, unique_key_(uniqueKey)
{
	shared_memory_.setKey(unique_key_);
	if (shared_memory_.attach())
	{
		is_running_ = true;
	}
	else
	{
		is_running_ = false;
		// create shared memory.
		if (!shared_memory_.create(1))
		{
			qDebug("Unable to create single instance.");
			return;
		}

		// create local server and listen to incoming messages from other instances.
		local_server_ = new QLocalServer(this);
		connect(local_server_, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
		local_server_->listen(unique_key_);
	}
}

// public slots.
void SingleApplication::onNewConnection()
{
	QLocalSocket* localSocket = local_server_->nextPendingConnection();
	if (!localSocket->waitForReadyRead(timeout_))
	{
		qDebug(localSocket->errorString().toLatin1());
		return;
	}

	QByteArray byteArray = localSocket->readAll();
	QString message = QString::fromUtf8(byteArray.constData());
	emit signalMessageAvailable(message);
	localSocket->disconnectFromServer();
}

// public functions.
bool SingleApplication::isRunning()
{
	return is_running_;
}

bool SingleApplication::sendMessage(const QString& message)
{
	if (!is_running_)
		return false;

	QLocalSocket localSocket(this);
	localSocket.connectToServer(unique_key_, 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;
}

测试程序

int main(int argc, char *argv[])
{
	//QApplication a(argc, argv);
	SingleApplication a(argc, argv, "6DE75305-A822-459E-9EDA-E8B038908966");
	if (a.isRunning())
	{
		a.sendMessage(BugReport::tr("Only one program instance is allowed to run."));
		return 0;
	}

	//
	YourApp w;
	QObject::connect(&a, SIGNAL(signalMessageAvailable(QString)), &w, SLOT(slotMessageAvailable(QString)));	
	w.show();

    return a.exec();
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:22:53  更:2022-04-18 17:26:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:49:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码