第7章 windows多线程编程
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
线程函数—CreateThread
lpThreadAttributes: 指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略 该参数。在Windows NT中,它被设为NULL,表示使用缺省值。 dwStackSize: 线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈 的大小。 lpStartAddress, 指向线程函数的指针,形式:函数名,函数名称没有限制,但是必须以下 列形式声明: DWORD WINAPI ThreadProc (LPVOID lpParam) ,格 式不正确将无法调用成功。 lpParameter: 向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为 NULL。 dwCreationFlags : 线程标志,可取值如下 (1) CREATE_SUSPENDED-----创建一个挂起的线 程 (2)0--表示创建后立即激活。 lpThreadId: 保存新线程的id。
VOID WINAPI Sleep( DWORD dwMilliseconds ); VOID ExitThread( DWORD dwExitCode);
线程睡眠
Βιβλιοθήκη Baidu
线程终结
void _endthread( void );
void _endthreadex( unsigned retval ); BOOL WINAPI TerminateThread( HANDLE hThread, DWORD dwExitCode);
BOOL WINAPI GetExitCodeThread( HANDLE hThread, DWORD lpExitCode)
获得线程返回值
线程的退出
释放操作系统资源
在程序结束前要清除线程及其所占资源
线程退出调用函数:
BOOL CloseHandle(HANDLE hObject);
void BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) { __try { ExitThread((pfnStartAddr)(pvParam)); } _except(UnhandledExceptionFilter (GetExceptionInformation())) { ExitProcess(GetExceptionCode()); } }
Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下, Windows内存管理器经常在内存中来回移动对象,依此来满足各种应 用程序的内存需要。对象被移动意味着它的地址变化 了。如果地址总 是如此变化,我们该到哪里去找该对象呢?为了解决这个问题, Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记 各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身 是不变的。
多 线下面程序首先创建两个线程,当输入为1时,执行线程,否则挂起线程。 #include <windows.h> 程 #include <iostream> 编 using namespace std; 程 DWORD WINAPI FunOne(LPVOID param) { 举 while(true) 例 { ( Sleep(1000); "; cout<<"hello! 示 } 例 } return 0; 二 DWORD WINAPI FunTwo(LPVOID param){ ) while(true)
多 线 程 编 程 举 例 ( 示 例 一 )
int main() //主函数 { int i=0; // Should be add in main code body #ifdef __INTEL_COMPILER printf("__INTEL_COMPILER = %d\n", __INTEL_COMPILER); #else printf("__INTEL_COMPILER is not defined.\n"); #endif _beginthread(ThreadFunc1,0,NULL); // _beginthread(ThreadFunc2,0,NULL); Sleep(3000); cout<<"end"<<endl; return 0; }
第7章 Windows多线程编程
Win32 API是Windows操作系统为内核以及应用程序之间提 供的接口,将内核提供的功能进行函数封装,应用程序通 过调用相关的函数获得相应的系统功能。 MFC是微软基础函数类库(Microsoft Foundation Classes),由 微软提供的,用类库的方式将Win32 API 进行封装, 以类的 方式提供给开发者。 .NET Framework 由 两 部 分 构 成 : 公 共 语 言 运 行 库 ( Common Language Runtime , CLR ) 和 Framework 类 库 ( Framework Class Library , FCL ) 。 .NET 基 础 类 库 的 System.Threading命名空间提供了大量的类和接口来支持多 线程。所有与多线程机制相关的类都存放在 System.Threading命名空间中。
Windows线程库介绍
使用win32线程API—HANDLE
句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。 应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单 地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这 个地址 访问对象。但是,如果您真的这样认为,那么您就大错特错了。
TerminateThread(hand1,1);TerminateThread(hand2,1);break;}
多 线 程 编 程 举 例 ( 示 例 三 )
/ exa3.cpp : Defines the entry point for the console application. #include <windows.h> #include <iostream> using namespace std; int globalvar = false; DWORD WINAPI ThreadFunc(LPVOID pParam) { cout<<"ThreadFunc"<<endl; Sleep(10); //Beep(5000,2000); globalvar = true; return 0; } int main() { HANDLE hthread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL); //创建 新线程 if (!hthread) { cout<<"Thread Create Error ! "<<endl; CloseHandle(hthread); } while (!globalvar) cout<<"Thread while"<<endl; // 主线程运行 cout<<"Thread exit"<<endl; getchar(); return 0;}
使用WIN32线程API — 线程函数
MyThreadStart(LPVOID p)即为线程的执行函数
也可以用_beginthread(多线程函数名,0,NULL) //须引入”process.h” uintptr_t _beginthread( void( *start_address )( void * ), unsigned stack_size, void *arglist ); start_address:程序执行一个新线程的起始地址 stack_size:新线程的堆栈大小或0 Arglist:传给新线程的变量清单或空 这是一个CRT(C/C++ Runtime Library)函数
线程的挂起与恢复
操作线程的API
进程中的每个线程都有挂起计数器(suspend count) 。当挂起计数器值为 0 时,线程被执行;当挂起计数器值大于0 时,调度器不去调度该线程。 DWORD SuspendThread(HANDLE hThread); DWORD ResumeThread(HANDLE hThread);
微软Win32/MFC 线程API
•创建线程 •管理线程 •使用Windows事件进行线程通信 •线程同步 •原子操作 •线程池 •线程优先级 •处理器亲和 •带有线程支持的用户级线程机制 •Windows多线程应用程序的编译和链接
使用win32线程API
Win32 函数库中提供了操作多线程的函数, 包括创建线程、管理线程、 终止线程、线程同步等接口。 线程函数 DWORD WINAPI ThreadFunc (LPVOID lpvThreadParm); 线程创建 HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
{
Sleep(1000); cout<<"world! ";
多线程编程举例(示例二)
int main(int argc, char* argv[]) { int input=0; HANDLE hand1= CreateThread (NULL, 0, FunOne, (void*)&input, CREATE_SUSPENDED, NULL); HANDLE hand2= CreateThread (NULL, 0, FunTwo, (void*)&input, CREATE_SUSPENDED, NULL); while(true){ cin>>input; if(input==1) if(input==0) if(input==2) }; return 0; } { { { ResumeThread(hand1); ResumeThread(hand2); SuspendThread(hand1); SuspendThread(hand2); } }
多线程基础—示例分析
多 线 程 编 程 举 例 ( 示 例 一 )
// exa1.cpp : Defines the entry point for the console application. #include <windows.h> #include <process.h> #include <iostream> #include <fstream> using namespace std; // 保证标准屏幕输入/输出语句的使用 void ThreadFunc1(PVOID param) { while(1) { Sleep(1000); cout<<"This is ThreadFunc1"<<endl; } } void ThreadFunc2(PVOID param) { while(1) { Sleep(1000); cout<<"This is ThreadFunc2"<<endl; } }
Windows中的句柄实际上是一个唯一的数字,它引用一个Windows对象, 例如窗口或者图标等。
使用win32线程API—HANDLE
Windows内存管理器在移动对象在内存中的位置后,把对象新的地址 告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间 接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load) 时由系统分配给的,当系统卸载时(Unload)又释放给系统。 句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址 (不稳定)→实际对象 但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程 序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假 如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系 统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门 票总是不同的一个座位是一样的道理。