3Sept.2008©NeusoftConfidentialLinux图形编程—QTQT编程—第11章进程和线程目标:本章旨在向学员介绍各种窗口部件:掌握Qt启动进程和线程的方法掌握进程间和线程间通讯方法学时:3学时教学方法:讲授ppt+上机操作+实例演示进程(QProgress)QProgress:QT提供了一个QProcess类用于启动一个外部程序并与之通信。QProcess::start():非阻塞QProcess::execute()阻塞,即execute()=start()+waitforFinished()QProgress可以挂起调用线程,等待相应的信号被发射Qprogress::waitForStarted():阻塞线程,直到进程启动Qprogress::waitForReadyRead():阻塞线程,直到有可读数据Qprogress::waitForBytesWritten():阻塞线程,直到写入bytes字节数据Qprogress::waitForFinished():阻塞线程,直到进程终了QProgress提供3种状态,并在状态改变时发射信号。注:QProgress继承自QIODevice,将进程视为IO设备,可以进行读写操作。•Starting•QProcess::start•Running•程序开始运行•NotRunning•程序退出•Q_SIGNALS:voidstarted();•Q_SIGNALS:voidfinished();进程间通信QT提供了多种方法实现进程间通信(IPC:Inter-ProcessCommunication)1TCP/IP通过QtNetwork模块,实现跨平台的网络通信。2共享内存:QShareMemory:实现操作系统内多个线程和进程访问共享内存段。3D-bus:QtDBus模块是一个UNIX库,可以使用D-Bus协议来进行进程通信,需要依赖第3方库。4Qt通信协议(QCOP)a.QCopChannel:实现了在客户端程序间使用有名管道通信,只用于嵌入式设备。b.QLocalSocket/QLocalServer:使用本地套接字进行服务,使用方法类似于QTcpSocket/QTcpServer。共享内存(QSharedMemory)共享内存(QSharedMemory):实现操作系统内多个线程和进程访问共享内存段。QSharedMemory::attach()挂载共享内存QSharedMemory::detach()卸载共享内存QSharedMemory::setKey()共享内存段标识QSharedMemory::create()创建内存QSharedMemory::lock()加锁内存QSharedMemory::unlock()解锁内存本地套接字本地套接字(QLocalSocket/QLocalServer):使用本地套接字进行服务,使用方法类似于QTcpSocket/QTcpServer。windows版本:有名管道实现UNIX版本:本地域套接字实现建立连接QLocalServer*serverserver-listen()QLocalSocket*socketsocket-connectToServer()socketQLocalSocket::readyRead()服务器进程客户进程SIGNAL(newConnection())QLocalServer::nextPendingConnection()QLocalSocket::write断开连接socket-disconnectFromServer()QLocalServer::SLOT(deleteLater()线程(QThread)QThread代表在应用程序中可以独立控制的线程,他与进程中的其他线程共享数据,但是独立运行。QThread::run():子类重写Run函数,实现线程逻辑。QThread::start():启动线程,它内部默认调用run函数。QThread提供的信号(Q_SIGNALS):voidstarted();线程启动后发射voidfinished();线程结束后发射voidterminated();线程终止后发射QThread提供的休眠函数:staticvoidsleep(unsignedlong):按秒为单位休眠staticvoidmsleep(unsignedlong):按毫秒为单位休眠staticvoidusleep(unsignedlong):按微秒为单位休眠同步函数:boolwait():让子线程和主线程同步线程内的事件机制:intexec():开启线程内的事件循环exit()或quit():退出事件循环互斥量(QMutex)QMutex类提供的是线程之间的访问顺序化,它的目的是保护一个对象、数据结构或者代码段,所以同一时间只有一个线程可以访问它。•QMutex::QMutex(boolrecursive=FALSE)–构造一个新的互斥量。这个互斥量是在没有锁定的状态下创建的。如果recursive为真,就构造一个递归互斥量,如果recursive为假(默认值),就构造一个普通互斥量。对于一个递归互斥量,一个线程可以锁定一个互斥量多次并且只有在相同数量的unlock调用之后,它才会被解锁。•QMutex::locked():–锁定一个互斥量•QMutex::unlock():–解锁这个互斥量•QMutex::tryLock():–试图锁定互斥量。如果锁被得到,这个函数返回真。如果另一个进程已经锁定了这个互斥量,这个函数返回假,而不是一直等到这个锁可用为止,注意,它不是阻塞的。•QMutexLocker:简化互斥量的锁定和解锁操作•QMutexLocker创建后,互斥量就锁定了。•QMutexLocker销毁的时候,自动实现互斥量解锁。•voidcomplexFunction(){QMutexLockerlocker(&mutex);//创建后锁定•……•}//退出函数后,栈对象销毁,自动解锁。读写锁(QReadWriteLock)读写锁(QReadWriteLock):QReadWriterLock对“read”,“write”访问进行区别对待,写线程执行的时候会阻塞所有的读线程,而读线程之间的运行不需要进行同步,使得多线程程序更具有并发性。QReadWriteLock::lockForRead()以读的方式加锁线程QReadWriteLock::lockForWrite()以写的方式加锁线程QReadLocker和QWriteLocker:是一组方便的类,可以自动死锁和解锁一个QReadWriteLock类。•QReadWriteLocklock;•voidReaderThread::run()•{•QReadLockerlocker(&lock);•read_file();•}•voidWriterThread::run()•{•QWriteLockerlocker(&lock);•write_file();•}线程种类读写读非阻塞阻塞写阻塞阻塞信号量(QSemaphore)信号量(Qsemaphore):也可以被用来使线程的执行顺序化,和QMutex的方法相似。信号量和互斥量的不同在于,信号量可以在同一时间被多于一个的线程访问。–QSemaphore::available():–返回信号量当前可使用的访问的数量。–QSemaphore::acquire()–试图得到信号量的访问。如果available()==0,这个调用将会阻塞,一直到它能够得到访问。–QSemaphore::release()释放信号量的访问。这将会唤醒所有等待访问这个信号量的线程。–QSemaphore::tryAcquire()尝试申请信号量资源,没有足够资源,该函数会立即返回。(非阻塞)•QSemaphoresem(5);//sem.available()==5•sem.acquire(3);//sem.available()==2•sem.acquire(2);//sem.available()==0•sem.release(5);//sem.available()==5•sem.release(5);//sem.available()==10•sem.tryAcquire(1);//sem.available()==9,returnstrue•sem.tryAcquire(250);//sem.available()==9,returnsfalse条件变量(QWaitCondition)条件变量(QWaitCondition):它允许线程在一定条件下唤醒其他线程。•1boolwait(QMutex*mutex,unsignedlongtime=ULONG_MAX)•mutex必须由调用线程进行初锁定。•释放锁定的mutex。•在线程对象上等待。•等待结束后恢复锁定状态。•2voidwakeAll()这将会唤醒所有等待QWaitCondition的线程。这些线程被唤醒的顺序依赖于操组系统的调度策略,并且不能被控制或预知。•3voidwakeOne()•这将会唤醒所有等待QWaitCondition的线程中的一个线程。这个被唤醒的线程依赖于操组系统的调度策略,并且不能被控制或预知。•谢谢!Copyright©2008版权所有东软集团