Windows 的抢先式多任务中的多线程编程

本文介绍了32位Windows系统中的多任务处理机制,包括抢先式多任务的特点、进程与线程的概念及其区别,以及如何通过MFC创建和终止线程。详细解释了线程的创建过程和线程函数的编写方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在32位的Windows系统中,采用的是抢先式多任务,这意味着程序对CPU的占用时间是由系统决定的。系统为每个程序分配一定的CPU时间,当程序的运行超过规定时间后,系统就会中断该程序并把CPU控制权转交给别的程序。与协同式多任务不同,这种中断是汇编语言级的。程序不必调用象PeekMessage这样的函数来放弃对CPU的控制权,就可以进行费时的工作,而且不会导致系统的挂起。

  例如,在Windows3.x 中,如果某一个应用程序陷入了死循环,那么整个系统都会瘫痪,这时唯一的解决办法就是重新启动机器。而在Windows 95/NT中,一个程序的崩溃一般不会造成死机,其它程序仍然可以运行,用户可以按Ctrl+Alt+Del键来打开任务列表并关闭没有响应的程序。

进程与线程

  在32位的Windows系统中,术语多任务是指系统可以同时运行多个进程,而每个进程也可以同时执行多个线程。

  进程就是应用程序的运行实例。每个进程都有自己私有的虚拟地址空间。每个进程都有一个主线程,但可以建立另外的线程。进程中的线程是并行执行的,每个线程占用CPU的时间由系统来划分。

  可以把线程看成是操作系统分配CPU时间的基本实体。系统不停地在各个线程之间切换,它对线程的中断是汇编语言级的。系统为每一个线程分配一个CPU时间片,某个线程只有在分配的时间片内才有对CPU的控制权。实际上,在PC机中,同一时间只有一个线程在运行。由于系统为每个线程划分的时间片很小(20毫秒左右),所以看上去好象是多个线程在同时运行。

  进程中的所有线程共享进程的虚拟地址空间,这意味着所有线程都可以访问进程的全局变量和资源。这一方面为编程带来了方便,但另一方面也容易造成冲突。

  虽然在进程中进行费时的工作不会导致系统的挂起,但这会导致进程本身的挂起。所以,如果进程既要进行长期的工作,又要响应用户的输入,那么它可以启动一个线程来专门负责费时的工作,而主线程仍然可以与用户进行交互。

2线程的创建和终止

  线程分用户界面线程和工作者线程两种。用户界面线程拥有自己的消息泵来处理界面消息,可以与用户进行交互。工作者线程没有消息泵,一般用来完成后台工作。

  MFC应用程序的线程由对象CWinThread表示。在多数情况下,程序不需要自己创建CWinThread对象。调用AfxBeginThread函数时会自动创建一个CWinThread对象。

  例如,清单12.2中的代码演示了工作者线程的创建。AfxBeginThread函数负责创建新线程,它的第一个参数是代表线程的函数的地址,在本例中是MyThreadProc。第二个参数是传递给线程函数的参数,这里假定线程要用到CMyObject对象,所以把pNewObject指针传给了新线程。线程函数MyThreadProc用来执行线程,请注意该函数的声明。线程函数有一个32位的pParam参数可用来接收必要的参数。

清单12.2 创建一个工作者线程

//主线程

pNewObject = new CMyObject;

AfxBeginThread(MyThreadProc, pNewObject);

//新线程

UINT MyThreadProc( LPVOID pParam )

{

CMyObject* pObject = (CMyObject*)pParam;

if (pObject == NULL ||  !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))

return -1; // 非法参数 

// 用pObject对象来完成某项工作

return 0; // 线程正常结束

} 

AfxBeginThread的声明为:

CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

 

  参数pfnThreadProc是工作线程函数的地址。pParam是传递给线程函数的参数。nPriority是线程的优先级,一般是THREAD_PRIORITY_NORMAL,若为0,则使用创建线程的优先级。nStackSize说明了线程的堆栈尺寸,若为0则堆栈尺寸与创建线程相同。dwCreateFlags指定了线程的初始状态,如果为0,那么线程在创建后立即执行,如果为CREATE_SUSPENDED,则线程在创建后就被挂起。参数lpSecurityAttrs用来说明保密属性,一般为0。函数返回新建的CWinThread对象的指针。

  程序应该把AfxBeginThread返回的CWinThread指针保存起来,以便对创建的线程进行控制。例如,可以调用CWinThread::SetThreadPriority来设置线程的优先级,用CWinThread::SuspendThread来挂起线程。如果线程被挂起,那么直到调用CWinThread::ResumeThread后线程才开始运行。

  如果要创建用户界面线程,那么必须从CWinThread派生一个新类。事实上,代表进程主线程的CWinApp类就是CWinThread的派生类。派生类必须用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏来声明和实现。需要重写派生类的InitInstance、ExitInstance、Run等函数。

  可以使用AfxBeginThread函数的另一个版本来创建用户界面线程。函数的声明为:

CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

  参数pThreadClass指向一个CRuntimeClass对象,该对象是用RUNTIME_CLASS宏从CWinThread的派生类创建的。其它参数以及函数的返回值与第一个版本的AfxBeginThread是一样的。

  当发生下列事件之一时,线程被终止:

线程调用ExitThread。

线程函数返回,即线程隐含调用了ExitThread。

ExitProcess被进程的任一线程显示或隐含调用。

用线程的句柄调用TerminateThread。

用进程句柄调用TerminateProcess。

首先可以在惠普官网下载Loadrunner12安装包。下载下来将会有四个安装包。 HP_LoadRunner_12.02_Community_Edition_Additional_Components_T7177-15060 社区版的附加组件 HP_LoadRunner_12.02_Community_Edition_Language_Packs_T7177-15062 社区版的语言包 HP_LoadRunner_12.02_Community_Edition_Standalone_Applications_T7177-15061 社区版独立应用程序 HP_LoadRunner_12.02_Community_Edition_T7177-15059 社区版。 以下我们直接安装社区版 作者:行水坐云 链接:https://www.jianshu.com/p/e781c85976fd 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。首先可以在惠普官网下载Loadrunner12安装包。下载下来将会有四个安装包。 HP_LoadRunner_12.02_Community_Edition_Additional_Components_T7177-15060 社区版的附加组件 HP_LoadRunner_12.02_Community_Edition_Language_Packs_T7177-15062 社区版的语言包 HP_LoadRunner_12.02_Community_Edition_Standalone_Applications_T7177-15061 社区版独立应用程序 HP_LoadRunner_12.02_Community_Edition_T7177-15059 社区版。 以下我们直接安装社区版 作者:行水坐云 链接:https://www.jianshu.com/p/e781c85976fd 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。首先可以在惠普官网下载Loadrunner12安装包。下载下来将会有四个安装包。 HP_LoadRunner_12.02_Community_Edition_Additional_Components_T7177-15060 社区版的附加组件 HP_LoadRunner_12.02_Community_Edition_Language_Packs_T7177-15062 社区版的语言包 HP_LoadRunner_12.02_Community_Edition_Standalone_Applications_T7177-15061 社区版独立应用程序 HP_LoadRunner_12.02_Community_Edition_T7177-15059 社区版。 以下我们直接安装社区版 作者:行水坐云 链接:https://www.jianshu.com/p/e781c85976fd 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。右键点击HP_LoadRunner_12.02_Community_Edition_T7177-15059.exe 安装程序,打开窗口中选择【以管理员身份运行】(若在Loadrunner安装完后直接点击运行有问题的话,可以采用此方式使用管理员身份尝试运行
以下是一些Xshell常用命令: 1. 查看文件详细信息:使用tail命令,例如:tail -f aaa.txt可以实时查看aaa.txt文件的内容\[1\]。 2. 创建一个空文件:使用touch命令,例如:touch aaa.txt可以创建一个名为aaa.txt的空文件\[1\]。 3. 编辑文件:可以使用vi或vim编辑器来编辑文件,例如:vi /etc/bubby.txt或vim /etc/bubby.txt可以编辑/etc/bubby.txt文件\[1\]。 4. 切换窗口和全屏:使用alt+1和alt+2可以切换窗口,使用alt+回车可以全屏\[1\]。 5. 挂起和恢复vim:使用ctrl+z可以将vim挂起,然后可以进行其他shell操作,使用fg命令可以切换回vim界面继续编辑\[1\]。 6. 查看端口号占用情况并杀死进程:使用netstat命令可以查看端口号占用情况,使用kill命令可以杀死指定进程\[2\]。 7. 编辑crontab:使用crontab -e命令可以进入编辑模式,使用:wq保存并退出,使用:q!退出不保存\[2\]。 8. 修改文件属主:使用chown命令可以修改文件的属主,例如:chown -R xh test1可以将test1目录及其子目录的所有文件的属主修改为xh\[3\]。 9. 设置系统时间和日期:使用clock和date命令可以设置系统的时间和日期\[3\]。 10. 查看内存和swap分区使用情况:使用free命令可以查看内存和swap分区的使用情况\[3\]。 11. 监视磁盘吞吐量:使用iostat命令可以监视磁盘的吞吐量\[3\]。 12. 查看最近登录系统的用户:使用last命令可以查看最近登录系统的用户\[3\]。 13. 查看命令的帮助:使用man命令可以查看某个命令的帮助内容\[3\]。 14. 关闭和重启计算机:使用reboot和shutdown命令可以关闭和重启计算机\[3\]。 15. 切换用户:使用su命令可以切换用户,例如:su -可以切换到root用户\[3\]。 16. 查看系统版本:使用uname命令可以查看系统的版本\[3\]。 17. 查看系统运行时间和负载:使用uptime命令可以查看系统的运行时间和负载\[3\]。 18. 监视虚拟内存使用情况:使用vmstat命令可以监视虚拟内存的使用情况\[3\]。 19. 显示登录用户的详细信息:使用w命令可以显示登录用户的详细信息\[3\]。 20. 显示登录用户:使用who命令可以显示登录用户\[3\]。 希望以上信息对您有所帮助! #### 引用[.reference_title] - *1* *2* *3* [Xshell常用命令大全](https://blog.youkuaiyun.com/weixin_67450855/article/details/129854733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值