作客户端开发已经有好几个年头了,今天看到同事发了一篇关于富途牛牛的文章,核心思想就是想说,新版本的富途支持多进程架构了,效率大大提高啦,能够更好的里有多核CPU,提供软件运行效率。微信
听到这个消息,我不只感叹,我靠,真的好牛逼。多线程
可是内心又在默默的想,这个东西到底有什么好处,多进程写界面!!!历来没这么搞过呀,会不会有坑,到底比多线程好在了哪里?带着这个问题,从百度上看了几篇相关文章,主要是讲解了线程和进程的一些区别。固然了,最重要的仍是目前的多进程架构的客户端已经开始变得多了起来。架构
其实很早之前就接触过多进程,支持本身好想也没有想那么多,一直对多进程架构的概念不是那么清晰。今天和同事聊了一些相关话题,感受本身的知识面豁然开朗,要学习的东西好像还挺多。函数
看下面这张图,是任务管理器的应用截图,之前还真是没发现,竟然我本身用的这么多应用都是多进程架构的。工具
咱们平时最经常使用的Chrome浏览器,客户端版本微信,还有有道云笔记等等
布局
有了这么多的多进程架构开发的客户端软件,难道说多进程开发已是势在必行了?学习
说这么多,还不如来点儿实际的干货,这篇文章是我初步开始使用多进程开发段产品的初步尝试,有不对的地方欢迎你们指出,能够给出更好建议测试
下面是我作的一个demo程序截图,测试程序中一共包含了4个使用场景,分别是:ui
你们能够先看看效果图,若是觉着有价值的能够继续往下看,下面我会分章节把四个事例进行讲解。
首先须要清楚,咱们是多进程界面开发,那么咱们的exe启动后,势必是须要启动其余可执行程序的,而且把其余进程的界面嵌入到咱们的窗口中来
启动外部进程有多重方式,Qt使用比较习惯的同窗能够直接使用QProcess类,这个类是Qt封装的一个跨平台的类。
启动方式可能像下面这样
QProcess * myProcess = new QProcess(this); QStringList arguments; myProcess->start("C:/Windows/System32/notepad.exe"); myProcess->waitForFinished(2000);
除过QProcess以外,Windows系统上咱们还可使用CreateProcess方法来建立进程。
QString cmd = "C:/Windows/system32/calc.exe"; STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = true; bool bRet = CreateProcess( NULL, (LPWSTR)cmd.toStdWString().c_str(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
外部进程启动后,咱们能够在任务管理器中找到启动的进程
接着咱们须要使用SPY++工具进行查看外部进程的类名称和窗口名称,并使用FindWindow接口进程查找,找到这个进程的主窗口句柄后,嵌入到咱们的程序中来。
类名和窗口名称查找过程能够参考外部进程嵌入到Qt进程界面这篇文章中的内容。
WId wid = (WId)FindWindow(QStringLiteral("Notepad").toStdWString().c_str() , QStringLiteral("无标题 - 记事本").toStdWString().c_str()); QWindow * window = QWindow::fromWinId(wid); if (window) { window->setFlags(window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint); //这边能够设置一下属性 QWidget * widget = QWidget::createWindowContainer(window, this, Qt::Widget); }
如上代码所示,咱们若是找到外部进程的主窗口句柄后,就可使用Qt提供的createWindowContainer这个接口进行建立QWidget,并加入到咱们的程序中来。
外部进程被封装成为一个QWidget后,咱们只须要加入到本身的布局中便可。
ui.verticalLayout_2->addWidget(widget);
接下来咱们分别讲解不一样场景下的多进程界面开发的简单使用
第三小节已经把嵌入其余程序的流程大体说了一遍,这里我就不在详细说明了,直接给出具体代码。
代码中比较关键的有2个地方
void EmbedCalculate::on_pushButton_2_clicked() { //建立进程 QString cmd = "C:/Windows/System32/notepad.exe"; QProcess * myProcess = new QProcess(this); QStringList arguments; myProcess->start(cmd); myProcess->waitForFinished(2000); WId wid = (WId)FindWindow(QStringLiteral("Notepad").toStdWString().c_str() , QStringLiteral("无标题 - 记事本").toStdWString().c_str()); QWindow * window = QWindow::fromWinId(wid); if (window) { window->setFlags(window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint); //这边能够设置一下属性 QWidget * widget = QWidget::createWindowContainer(window, this, Qt::Widget); ui.verticalLayout_2->addWidget(widget); } }
ping命令使用场景主要是想展现主进程和外部进程是怎样通讯的,虽然这个事例比较简单,但也算是二者之间发生了信息交换
子进程在执行完ping一个地址以后,会把获得的结果传递给主进程,主进程使用readAll函数所有读入到主进程中。
void EmbedCalculate::on_pushButton_3_clicked() { //建立进程 QProcess * myProcess = new QProcess(this); connect(myProcess, static_cast<void (QProcess::*)(int)>(&QProcess::finished), this, [this, myProcess](int exitCode){ if (exitCode == 0) { QTextCodec * gbkCodec = QTextCodec::codecForName("GBK"); QString result = gbkCodec->toUnicode(myProcess->readAll()); ui.textEdit->setText(result); } }); //myProcess->start("cmd.exe", QStringList() << "/c" << "ping www.baidu.com"); myProcess->start("cmd.exe", QStringList() << "/c" << "ping " + ui.lineEdit->text().trimmed()); myProcess->waitForFinished(2000); ··· }
虽然这个东西是最后讲的,可是这个才是重头戏,有了这个实验以后,咱们之后的Qt多进程界面开发也能够进行投入正式环境了。
以下所示,ChildWidget外部程序的主窗体被咱们嵌入到了EmbedCalculate这个进程的主界面上,忽然觉着好神奇,给本身点赞,哈哈哈哈。
因为我这里的ChildWidget外部程序和EmbedCalculate主程序在一个目录中,所以cmd变量直接就指向了ChildWidget这个外部程序的名称。
其余部分的代码基本上就和前边几种使用场景差很少。
void EmbedCalculate::on_pushButton_4_clicked() { //建立进程 QString cmd = "ChildWidget.exe"; QProcess * myProcess = new QProcess(this); QStringList arguments; myProcess->start(cmd); myProcess->waitForFinished(2000); WId wid = (WId)FindWindow(QStringLiteral("Qt5QWindowIcon").toStdWString().c_str() , QStringLiteral("ChildWidget").toStdWString().c_str()); QWindow * window = QWindow::fromWinId(wid); if (window) { window->setFlags(window->flags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint); //这边能够设置一下属性 QWidget * widget = QWidget::createWindowContainer(window, this, Qt::Widget); ui.verticalLayout_3->addWidget(widget); } }
以上的内容,基本上就是本篇文章的内容全部内容啦!序列化和反序列化功能基本完成,但愿能够帮到你们。
![]() |
![]() |
很重要--转载声明