qnetworkreply渣男什么情况下会回头回...

您所在位置: &
 &  & 
智能冰箱食品管理系统设计与实现.pdf 75页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:200 &&
智能冰箱食品管理系统设计与实现
你可能关注的文档:
??????????
??????????
--------------------------Page1------------------------------ATHESISSUBMITTEDINPARTIALFULFILLMENTOFTHEREQUIREMENTSFORTHEDEGREEFORTHEMASTEROFENGINEERINGAMasterThesisSubmittedtoUniversityofElectronicScienceandTechnologyofChinaMajor:MasterofEngineeringAuthor:ZhaoZixianAdvisor:Prof.GuiXunInstituteofElectronicandInformationSchool:EngineeringinDongguan,UESTC--------------------------Page2--------------------------------------------------------Page3------------------------------独创性声明本人声明所呈交的学位论文是本人在导师指导下进行的研究工作及取得的研究成果。据我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得电子科技大学或其它教育机构的学位或***而使用过的材料。与我一同工作的同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示谢意。作者签名:日期:年月日论文使用授权本学位论文作者完全了解电子科技大学有关保留、使用学位论文的规定,有权保留并向国家有关部门或机构送交论文的复印件和磁盘,允许论文被查阅和借阅。本人授权电子科技大学可以将学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存、汇编学位论文。(保密的学位论文在解密后应遵守此规定)作者签名:导师签名:日期:年月日--------------------------Page4--------------------------------------------------------Page5------------------------------摘要摘要随着人民生活水平的飞速发展,生活节奏不断加快,冰箱在家庭中起的作用也越来越大,大量的食品放进冰箱,给现代人的生活带来很多方便。但是冰箱内的食品多了,一方面如果不能及时食用这些食品,很容易过期而造成不必要的浪费,另一方面容易搞不清楚哪些食品已经用完,而不能及时购买补充。本课题使用Intel嵌入式微处理器PXA270构建硬件平台,嵌入式Linux为操作系统,以QT4.7为开发工具,采用射频识别(RFID),有线网络接入,网络安全,SQLite数据库等技术,开发一套拥有网络购物功能,能够智能管理冰箱内各类食品的智能冰箱系统。食品的跟踪管理依赖RFID技术,读写器和标签通信协议采取半双工的方式,读写器处于主导地位,即读写器先说,标签不会自己主动向读写器发送数据。采用一种有效的抗冲突方法,解决多个标签同时进入读写器的读写范围而产生冲突的问题,并在使用该抗冲突方法的基础上,减少电路复杂度,减少对存储器的需求,从而实现低功耗和低成本的优化。智能冰箱系统的应用为都市人群忙碌的生活提供便捷,解决众多生活琐碎事情,让人们可以更加专注自己的工作、学业;同时,也可以衍生为其他的商业应用,比如基于RFID的智能超市,极大的促进物联网的发展。智能冰箱系统对放进冰箱的食品进行全程定向跟踪,冷藏食品信息随手可得,能用电脑查找适合手头原料的菜谱,还可以通过手机就查看冰箱里还有多少食物,可以满足未来智能家居的需求。关键词:LinuxRFID物联网智能网上购物--------------------------Page6--------------------------------------------------------Page7------------------------------ABSTRACTABSTRACTWiththerapiddevelopmentofthepeople'slivingstandardsandtheacceleratingpaceoflife,fridgesplayagreatroleinfamilies,whicharehandyformodernlife.However,moreandmorefoodinit,ontheonehand,itislikelytoexpireandcauseunnecessarywasteifyouarenoteatingtheseontheotherhand,peoplecan'tf
正在加载中,请稍后...Qt 学习之路 2(75):线程总结
Qt 学习之路 2(75):线程总结
发布时间: 7:03:59
编辑:www.fx114.net
本篇文章主要介绍了"Qt 学习之路 2(75):线程总结 ",主要涉及到Qt 学习之路 2(75):线程总结 方面的内容,对于Qt 学习之路 2(75):线程总结 感兴趣的同学可以参考一下。
前面我们已经详细介绍过有关线程的一些值得注意的事项。现在我们开始对线程做一些总结。
有关线程,你可以做的是:
在QThread子类添加信号。这是绝对安全的,并且也是正确的(前面我们已经详细介绍过,发送者的线程依附性没有关系)
不应该做的是:
调用moveToThread(this)函数
指定连接类型:这通常意味着你正在做错误的事情,比如将QThread控制接口与业务逻辑混杂在了一起(而这应该放在该线程的一个独立对象中)
在QThread子类添加槽函数:这意味着它们将在错误的线程被调用,也就是QThread对象所在线程,而不是QThread对象管理的线程。这又需要你指定连接类型或者调用moveToThread(this)函数
使用QThread::terminate()函数
不能做的是:
在线程还在运行时退出程序。使用QThread::wait()函数等待线程结束
在QThread对象所管理的线程仍在运行时就销毁该对象。如果你需要某种&自行销毁&的操作,你可以把finished()信号同deleteLater()槽连接起来
那么,下面一个问题是:我什么时候应该使用线程?
首先,当你不得不使用同步 API 的时候。
如果你需要使用一个没有非阻塞 API 的库或代码(所谓非阻塞 API,很大程度上就是指信号槽、事件、回调等),那么,避免事件循环被阻塞的解决方案就是使用进程或者线程。不过,由于开启一个新的工作进程,让这个进程去完成任务,然后再与当前进程进行通信,这一系列操作的代价都要比开启线程要昂贵得多,所以,线程通常是最好的选择。
一个很好的例子是地址解析服务。注意我们这里并不讨论任何第三方 API,仅仅假设一个有这样功能的库。这个库的工作是将一个主机名转换成地址。这个过程需要去到一个系统(也就是域名系统,Domain Name System, DNS)执行查询,这个系统通常是一个远程系统。一般这种响应应该瞬间完成,但是并不排除远程服务器失败、某些包可能会丢失、网络可能失去链接等等。简单来说,我们的查询可能会等几十秒钟。
UNIX 系统上的标准 API 是阻塞的(不仅是旧的gethostbyname(3),就连新的getservbyname(3)和getaddrinfo(3)也是一样)。Qt 提供的QHostInfo类同样用于地址解析,默认情况下,内部使用一个QThreadPool提供后台运行方式的查询(如果关闭了 Qt 的线程支持,则提供阻塞式 API)。
另外一个例子是图像加载和缩放。QImageReader和QImage只提供了阻塞式 API,允许我们从设备读取图片,或者是缩放到不同的分辨率。如果你需要处理很大的图像,这种任务会花费几十秒钟。
其次,当你希望扩展到多核应用的时候。
线程允许你的程序利用多核系统的优势。每一个线程都可以被操作系统独立调度,如果你的程序运行在多核机器上,调度器很可能会将每一个线程分配到各自的处理器上面运行。
举个例子,一个程序需要为很多图像生成缩略图。一个具有固定 n 个线程的线程池,每一个线程交给系统中的一个可用的 CPU 进行处理(我们可以使用QThread::idealThreadCount()获取可用的 CPU 数)。这样的调度将会把图像缩放工作交给所有线程执行,从而有效地提升效率,几乎达到与 CPU 数的线性提升(实际情况不会这么简单,因为有时候 CPU 并不是瓶颈所在)。
第三,当你不想被别人阻塞的时候。
这是一个相当高级的话题,所以你现在可以暂时不看这段。这个问题的一个很好的例子是在 WebKit 中使用QNetworkAccessManager。WebKit 是一个现代的浏览器引擎。它帮助我们展示网页。Qt 中的QWebView就是使用的 WebKit。
QNetworkAccessManager则是 Qt 处理 HTTP 请求和响应的通用类。我们可以将它看做浏览器的网络引擎。在 Qt 4.8 之前,这个类没有使用任何协助工作线程,所有的网络处理都是在QNetworkAccessManager及其QNetworkReply所在线程完成。
虽然在网络处理中不使用线程是一个好主意,但它也有一个很大的缺点:如果你不能及时从 socket 读取数据,内核缓冲区将会被填满,于是开始丢包,传输速度将会直线下降。
socket 活动(也就是从一个 socket 读取一些可用的数据)是由 Qt 的事件循环管理的。因此,阻塞事件循环将会导致传输性能的损失,因为没有人会获得有数据可读的通知,因此也就没有人能够读取这些数据。
但是什么会阻塞事件循环?最坏的***是:WebKit 自己!只要收到数据,WebKit 就开始生成网页布局。不幸的是,这个布局的过程非常复杂和耗时,因此它会阻塞事件循环。尽管阻塞时间很短,但是足以影响到正常的数据传输(宽带连接在这里发挥了作用,在很短时间内就可以塞满内核缓冲区)。
总结一下上面所说的内容:
WebKit 发起一次请求
从服务器响应获取一些数据
WebKit 利用到达的数据开始进行网页布局,阻塞事件循环
由于事件循环被阻塞,也就没有了可用的事件循环,于是操作系统接收了到达的数据,但是却不能从QNetworkAccessManager的 socket 读取
内核缓冲区被填满,传输速度变慢
网页的整体加载时间被自身的传输速度的降低而变得越来越坏。
注意,由于QNetworkAccessManager和QNetworkReply都是QObject,所以它们都不是线程安全的,因此你不能将它们移动到另外的线程继续使用。因为它们可能同时有两个线程访问:你自己的和它们所在的线程,这是因为派发给它们的事件会由后面一个线程的事件循环发出,但你不能确定哪一线程是&后面一个&。
Qt 4.8 之后,QNetworkAccessManager默认会在一个独立的线程处理 HTTP 请求,所以导致 GUI 失去响应以及操作系统缓冲区过快填满的问题应该已经被解决了。
那么,什么情况下不应该使用线程呢?
这可能是最容易误用线程的情况了。如果我们需要每隔一段时间调用一个函数,很多人可能会这么写代码:
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:在处理QT循环事件的时候遇到了问题,查了半天资料都没弄明白问题出在哪,后来找大牛同事问了一下,同事就给我写了QCoreApplication::processEvent()这个函数,好啦,终于搞定了,这里小记一下,以免以后遇到。
于是乎这里认真仔细的看了一下Qt的事件和事件循环。(引用了碎炎的博客)
事件和事件循环
作为一个事件驱动的工具包,事件和事件传递扮演者Qt架构中的中心角色。在本文中我们不会给出一个对这个话题的全面的概述,我们将着眼于一些线程相关的概念。
事件能被程序的内部和外部产生,举个例子:
QKeyEvent和QMouseEvent对象代表了一个键盘和鼠标的事件,它们从窗口由用户的操作而产生。
QTimerEvent对象是当某个时间被激发时投入,它们都由操作系统产生。
QChildEvent对象是当一个子窗口被添加或者移除时候被送入QObject的,它们的源头是Qt程序自己。
事件的重点是它们被产生的时候不会被传递;它们会先进入事件队列,某刻会被传递。传送者自己循环访问事件队列并把事件传递给目标QObject对象,因此称作事件循环。概念上说,时间循环就像这个:
1.&& while&(is_active)
3.&& & &&while&(!event_queue_is_empty)
4.&& & & & & dispatch_next_event();
6.&& & & wait_for_more_events();
我们通过运行QCoreApplication::exec()来进入消息循环,这个循环直到exit()或者quit()被调用时才会被堵塞,然后退出。
这个&wait_for_more_events()&函数处于堵塞状态,直到有新的事件被产生了。假如我们考虑它,所有在此刻可能产生的事件是外部源头的。因此,这个消息循环能被以下情况唤醒:
窗口管理活动(鼠标按键操作等);
套接字事件;
定时器事件;
其它线程中投递的事件、
在Unix-like系统中,窗口管理器通过套接字来通知应用程序,即使客户端使用它们来与x server通讯。如果我们决定用内部的套接字对去实现跨线程的事件投递,所有剩下的唤醒条件如下:
这个就是select(2)系统调用所做的;它监视着一系列的一系列的活动者的描述符,如果它们在一定的时间内没有特定的活动,它们就超时了。
一个运行着的事件循环需要什么?
这个不是完整的列表,但是如果你有整体画面,你将能够去猜测什么类需要一个运行着的事件循环。
Widgets的绘画和互动:QWidget::paintEvent()将在传递QPaintEvent对象时候被调用,这个对象将会在调用QWidget::update()或者窗口管理器的时候产生:响应的事件将需要一个时间循环去分发。
Timers:长话短说,它们在当select(2)或者超时的时候产生,因此它们需要让Qt在返回时间循环的时候作这些调用。
Networking&所有的底层Qt网络类 (QTcpSocket,QUdpSocket,QTcpServer等)都是异步设计的。当你调用ready(),它们只是返回已经可用的数据,当你调 用write(),它们只是将这个操作放入队列,适时会写入。只有当你返回消息循环的时候真实的读取,写入才会执行。注意它们确实提供了同步的方法,但是 它们的用法是不被提倡的,因为它们会堵塞事件循环。高级类,比如QNetworkAccessManager,简单的不提供同步API,需要一个事件循 环。
堵塞事件循环
在我们讨论为什么你应该从不堵塞消息循环之前,我们试着分析堵塞的含义。假象你有一个按钮,它将会在它被点击的时候发出clicked信号;在我们的对象中连接着一个槽函数,当你点击了那个按钮后,栈追踪将会像这样:
1.&&&& main(int, char **)
2.&&&& QApplication::exec()
3.&&&& [&]
4.&&&& QWidget::event(QEvent *)
5.&&&& Button::mousePressEvent(QMouseEvent *)
6.&&&& Button::clicked()
7.&&&& [&]
8.&&&& Worker::doWork()
在main函数中我们启动了时间循环,平常的调用了 exex(),窗口管理器给我们发送了一个鼠标点击事件,它被Qt内核取走,转换成QMouseEvent并被送往我们widget的event()方 法,该方法被QApplication::notify()发送。因为按钮没有重写event(),基类方法将被调用,QWidget::event() 检测到了这个事件确实是一个鼠标点击事件,然后调用特定的事件处理函数,那就是Button::mousePressEvent(),我们重写这个方法去 发送clicked()信号,这将会调用被连接的槽函数。
当该对象处理量很大,那么消息循环在作什么?我们应该猜测它:什么都不做!它分发鼠标按下事件,然后就堵塞着等待着事件处理函数返回。这个就是堵塞了时间循环,它意味着没有消息被分发了,知道我们从槽函数返回了,然后继续处理挂起的消息。
在消息循环被卡住的情况下,widgets将不能更新它们 自身,不可能有更多的互动,timers将不会被激发,网络通讯将缓慢下来,或者停止。进一步的说,许多窗口管理器将检测到你的应用程序不在处理事件了, 然后告诉用户你的程序没有响应。这就是为什么快速的对事件响应并且即时返回到事件循环是多么的重要!
强制事件分发
所以,假如我们有一个很长的任务去运行但是又不希望堵塞这 个消息循环,该怎么做呢?一个可能的回答是将这个任务移到另一个线程中,在下一个张洁我们将看到这是如何做的。我们也能手动强制事件循环去运行,这个方法 是通过在堵塞的任务函数中调用QCoreApplication::processEvent()来实现 的,QCoreApplication::processEvent()将处理所有在消息队列中的消息并返回给调用者。
另一个可选的选项是我们能够强制重入事件循环的对象,就是QEventLoop类。通过调用QEventLoop::exec()我们将重入事件循环,然后我们能将槽函数QVentLoop::quit()连接到信号上去使它退出。举个例子:
1.&& &qnam;
2.&& &*reply&=&qnam.get(((...)));
3.&& &loop;
4.&& ::connect(reply,&SIGNAL(finished()),&&loop,&SLOT(quit()));
5.&& loop.exec();
6.&& /* reply has finished, use it */
QNetworkReply不提供堵塞的API,它要求一个在运行的事件循环。我们进入了一个本地的事件循环,然后当回复完成时候,这个本地的循环退出了。
要特别小心的是在其它路径下重入事件循环:它可能导致不希望的递归!让我们回到前面看看按钮的例子。假如我们在槽函数中调用了QCoreApplication::processEvent(),当用户点击了这个按钮,这个槽函数将被再次调用:
1.&&&& main(int, char **)
2.&&&& QApplication::exec()
3.&&&& [&]
4.&&&& QWidget::event(QEvent *)
5.&&&& Button::mousePressEvent(QMouseEvent *)
6.&&&& Button::clicked()
7.&&&& [&]
8.&&&& Worker::doWork() //&first, inner invocation
9.&&&& QCoreApplication::processEvents() //&we manually dispatch events and&
11.&& QWidget::event(QEvent * ) //&another mouse click is sent to the Button&
12.&& Button::mousePressEvent(QMouseEvent *)
13.&& Button::clicked() //&which emits clicked() again&
15.&& Worker::doWork() //&DANG! we&ve recursed into our slot.
一个快速并简便的变通方法是把QEventLoop::ExcludeUserInputEvent传递给QCoreApplication::processEvents(),这会告诉消息循环不要再次分发任何用户的输入事件。
幸运的是,这个相同的事情不会在检测事件中发生。事实上,它们被Qt通过特殊的方法处理了,只有当运行的时间循环有了一个比deleteLater被调用后更小的&nesting&值才会被处理:
1.&& &*object&=&new&QObject;
2.&& object-&deleteLater();
3.&& &dialog;
4.&& dialog.exec();
将不会使object成为一个悬空指针。相同的东西被应用 到了本地的事件循环中。唯一的一个显著区别我已经发现了,它在假如当没有事件循环在运行的时候deleteLater被调用了的条件下,然后第一个消息循 环进入了后会取走这个事件,然后删除这个object。这是相当合理的,因为Qt不知道任何外部的循环将最终影响这个检测,因此马上删除了这个 object。
阅读(...) 评论()

参考资料

 

随机推荐