版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第四章 Windows多线程编程小节章节重点内容4.1Windows线程库介绍介绍4.2使用Win32线程API创建;管理;终结;多线程综合4.3线程执行和资源存取线程间通信4.4多线程调试与优化技术调优方法和技巧4.1 Windows线程库介绍在Windows平台下可以通过Windows的线程库来实现多线程编程。可以利用Win32 API或MFC以及.Net Framework提供的接口来实现。对于多线程程序可以使用Visual Studio调试工具进行调试,也可以使用多核芯片厂家的线程分析调试工具进行调试。234.1 Windows线程库Win32 APIWindows操作系统为内核以及
2、应用程序之间提供的接口将内核提供的功能进行函数封装应用程序通过调用相关的函数获得相应的系统功能。MFC微软基础函数类库(Microsoft Foundation Classes)用类库的方式将Win32 API 进行封装, 以类的方式提供.NETFramework构成公共语言运行库(CommonLanguageRuntime,CLR)文件加载器、垃圾收集器、安全系统Framework类库(FrameworkClassLibrary,FCL).NET 基础类库的System.Threading命名空间提供了类和接口支持多线程所有与多线程机制相关的类都存放在System.Threading命名空间
3、中44.2 win32线程APIWin32 函数库中提供了操作多线程的函数, 包括创建线程、管理线程、终止线程、线程同步等接口。线程函数(线程开始执行的函数)DWORD WINAPI ThreadFunc (LPVOID lpvThreadParm);线程创建HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDW
4、ORD lpThreadId );如果创建成功则返回线程的句柄,否则返回NULL。第一个参数lpThreadAtt,是一个指向SECURITY- ATTRIBUTES结构的指针,该结构制定了线程的安全属性,缺省为 NULL。第二个参数dwStackSize,是栈的大小,一般设置为0。第三个参数lpFun是新线程开始执行时,线程函数的入口地址。它必须是将要被新线程执行的函数地址,不能为NULL。第四个参数lpParameter,是线程函数定义的参数。可以通过这个参数传送值,包括指针或者NULL 。第五个参数dwCreationFlags,控制线程创建的附加标志,可以设置两种值。0表示线程在被创建
5、后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;第六个参数lpThreadID,为指向32位变量的指针,该参数接受所创建线程的ID号。5_beginthreadCreateThread不会执行C运行时数据块, 因此在C运行时库的应用程序中,不能使用CreateThread创建线程,微软提供了另外的创建线程的方法:创建线程用process.h头文件中声明的C执行时期链接库函数_beginthread。语法:hThread = _beginthread (void( _cdecl *sta
6、rt_address )( void * ), unsigned stack_size, void *arglist) ; 线程函数的语法:void _cdecl ThreadProc (void * pParam) ; 7使用_beginthread创建线程实例 #include stdafx.h#include #include #include #include using namespace std;void ThreadFunc1(PVOID param) while(1) Sleep(1000); coutThis is ThreadFunc1endl; void ThreadFu
7、nc2(PVOID param) while(1) Sleep(1000); coutThis is ThreadFunc2endl; int main() int i=0; _beginthread ( ThreadFunc1, 0, NULL); _beginthread ( ThreadFunc2, 0, NULL); Sleep(3000); coutendendl; return 0; 8创建线程CreateThread, _beginThread、beginThreadx AfxBeginThread关系9104.2.2 线程管理设置线程的优先级一个线程被创建时,它的优先级等于它所
8、属进程的优先级调用SetThreadPriority函数设置线程的相对优先级,例如Bool SetThreadPriority (HANDLE hPriority , int nPriority)参数hPriority 指向待设置的线程句柄线程与包含它的进程的优先级关系如下:线程优先级 = 进程优先级 + 线程相对优先级4.2.2 线程管理进程的优先级包括:实时:REALTIME_PRIORITY_CLASS;高:HIGH _PRIORITY_CLASS;高于正常:ABOVE_NORMAL_PRIORITY_CLASS;正常:NORMAL _PRIORITY_CLASS;低于正常:BELOW_
9、 NORMAL _PRIORITY_CLASS;空闲:IDLE_PRIORITY_CLASS。nPriority 是线程的相对优先级,可以是以下的值:空闲:THREAD - PRIORITY- IDLE 15 最低线程:THREAD - PRIORITY- LOWEST 2低于正常线程:THREAD - PRIORITY- BELOW- NORMAL 1正常线程:THREAD - PRIORITY- NORMAL 0高于正常线程:THREAD - PRIORITY- ABOVE NORMAL -1最高线程:THREAD - PRIORITY- HIGHEST -2关键时间:THREAD - P
10、RIORITY- TIME CRITICAL -1511线程的挂起与恢复进程中的每个线程都有挂起计数器当挂起计数器值为0 时,线程被执行当挂起计数器值大于0 时,调度器不去调度该线程。线程的挂起计数器的值不能够直接被访问可以通过调用Windows API函数来改变它的值通过调用 SuspendThread( )函数来挂起;通过调用 ResumeThread( )函数来恢复;12线程的挂起与恢复挂起与恢复函数原型DWORD SuspendThread(HANDLE hThread);挂起指定的线程如果函数执行成功,则线程的执行被终止每次调用SuspendThread() 函数,线程将挂起计数器的
11、值增1 DWORD ResumeThread(HANDLE hThread);结束线程的挂起状态来执行这个线程每次调用ResumeThread() 函数,线程将挂起计数器的值减1若挂起计数器的值为0,则不会再减13线程等待Win32 API提供了一组能使线程阻塞其自身执行的等待函数WaitForSingleObjectWaitForMultipleObject这些函数在其参数中的一个或多个同步对象中产生了信号,或者在超过规定的等待时间才会返回在等待函数未返回时,线程处于等待状态,线程只消耗很少的CPU时间14线程终结在线程函数返回时,线程自动终止在线程的执行过程中终止则可调用函数:VOID E
12、xitThread (DWORD dwExitCode) ;如果在线程的外面终止线程,则可调用下面的函数:BOOL TerminateThread (HANDLE hThread, DWORDdw ExitCode) ;15184.3 线程间的通信线程之间通信的两个基本问题是互斥和同步同步指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应该等待,直到消息到达时才被唤醒。互斥是指对于共享资源,在各线程访问时的排它性线程互斥是一种特殊的线程同步 Win32中实现线程同步的机制全局变量事件(Event)临界区(Critical section)互斥量
13、(Mutex)信号量(Semaphore)19Win32中的线程同步机制全局变量进程中的所有线程均可以访问所有的全局变量,因而全局变量成为Win32多线程通信的最简单方式。 int var; /全局变量 UINT ThreadFunction ( LPVOID pParam while (var) /线程处理 return 0; var是一个全局变量,任何线程均可以访问和修改。线程间可以利用此特性达到线程同步的目的。用全局变量实现线程同步的实例 #include #include using namespace std;int globalvar = false;DWORD WINAPI Th
14、readFunc(LPVOID pParam)coutThreadFuncendl;Sleep(200);globalvar = true;return 0;int main()HANDLE hthread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);if (!hthread)coutThread Create Error ! endl;CloseHandle(hthread);while (!globalvar) coutThread whileendl;coutThread exitendl;return 0;20 问题:主线程等待
15、globalvar为真,如不为真则一直循环,这样占用了CPU资源如果主线程优先级高于ThreadFunc,则globalvar一直不会被置为真事件(event)事件是WIN32提供的最灵活的线程间同步方式。事件存在两种状态:激发状态(signaled or true)未激发状态(unsignal or false)事件可分为两类:手动设置:这种对象只能用程序来手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。SetEvent只有一个参数,该参数指定了事件对象的句柄值,若事件成功激发,返回TRUE;ResetEvent函数将事件对象恢复到最初的非激发状态
16、,只有一个参数,成功后返回真自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。21创建事件的函数原型为: HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName );其中:第一个参数:与CreateThread中的第一个参数类似,是一个指向SECURITY- ATTRIBUTES结构的指针第二个参数:代表事件的类型,是手动清除事件信号还是自动清除事件信号。TRUE为手动清除。第三个参数:指明事件的初
17、始状态第四个参数:事件的名称22使用“事件”机制应注意:(1)设置事件是否要自动恢复;(2)设置事件的初始状态;(3)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突事件对象的使用事件对象属于内核对象进程A可以通过调用OpenEvent函数根据对象的名字获得进程B中event对象的句柄,然后对这个句柄可以使用ResetEvent、SetEvent和WaitForMultipleObjects等函数进行操作来实现一个进程的线程控制另一进程中线程的运行 当程序中一个线程的运行要等待另外一个线程中一项特定的操作的完成才能继续执行时,就可以使用事
18、件对象来通知等待线程某个条件已满足23事件机制的应用有三个线程主线程、读线程ReadThread、写线程WriteThread 读线程ReadThread必须在写线程WriteThread 的写操作完成之后才能进行读操作主线程必须在读线程ReadThread 的读操作完成后才结束定义两个事件对象evRead,evFinishevRead由写线程WriteThread用于通知读线程ReadThread 进行读操作evFinish由读线程ReadThread用于通知主线程读操作已经结束24#include stdafx.h#include #include #include #include us
19、ing namespace std;HANDLE evRead, evFinish;void ReadThread(LPVOID param)WaitForSingleObject (evRead, INFINITE);coutReadingendl;SetEvent (evFinish);void WriteThread(LPVOID param)coutWritingendl;SetEvent (evRead);int main(int argc , char * argv)evRead = CreateEvent (NULL ,FALSE ,FALSE ,NULL) ;evFin = C
20、reateEvent (NULL ,FALSE ,FALSE ,NULL) ;_beginthread(ReadThread , 0 , NULL) ;_beginthread(WriteThread , 0 , NULL) ; WaitForSingleObject (evFinish, INFINITE) ;coutThe Program is End= 0) total -= 90 ; coutYou withdraw 90endl;else coutYou do not have that much moneyendl; LeaveCriticalSection(&cs) ;SetEv
21、ent (evFin0) ;int main(int argc , char * argv)evFin0 = CreateEvent (NULL,FALSE,FALSE,NULL) ;evFin1 = CreateEvent (NULL,FALSE,FALSE,NULL) ;InitializeCriticalSection(&cs) ;_beginthread(WithdrawThread1 , 0 , NULL) ;_beginthread(WithdrawThread2 , 0 , NULL) ; WaitForMultipleObjects(2 ,evFin ,TRUE ,INFINI
22、TE) ; DeleteCriticalSection(&cs) ;couttotalendl;return 0 ;31重点语句练 习在图书馆里,读者1和读者2借书 X (X为书名)。假设该书有10本。只要有就可以借。请用使用临界区模拟读者1、读者2的一次借书过程。32互斥量通常用于协调多个线程或进程的活动,通过对资源“锁定”和“取消锁定”,来控制对共享资源的访问。当一个互斥量被一个线程锁定了,其他试图对其加锁的线程就会被阻塞;当对互斥量加锁的线程解除锁定后,则被阻塞的线程中的一个会得到互斥量。互斥量的作用是保证每次只能有一个线程获得互斥量使用CreateMutex函数创建: HANDLE C
23、reateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, /安全属性 BOOL bInitialOwner, /初始化对象是否拥有该互斥量,TRUE为立刻拥有 LPCTSTR lpName /互斥量名称 );33OpenMutex 打开并返回一个已存在的互斥对象的句柄,使之后续访问;HANDLE OpenMutex( DWORD dwDesiredAccess, / 访问参数 BOOL bInheritHandle, / 如果希望子进程继承该句柄,则为TRUE LPCTSTR lpName / 互斥量名);其中 dwDesireAccess: M
24、UTEX_ALL_ACCESS 请求对互斥体的完全访问 MUTEX_MODIFY_STATE 允许使用 ReleaseMutex 函数 SYNCHRONIZE 允许互斥体对象同步使用ReleaseMutex(HANDLE handle)释放对互斥对象的占用,使之成为可用;34使用互斥量的一般方法是: void Writedata() WaitForSingleObject(hMutex,); ./do something ReleaseMutex(hMutex); 35请推测教材P97页程序的输出结果。36互斥量使用的实例#define THREAD_INSTANCE_NUMBER 3LONG
25、 g_fResourceInUse = FALSE;LONG g_lCounter = 0;DWORD ThreadProc(void * pData) int ThreadNumberTemp = (*(int*) pData);HANDLE hMutex;if (hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, Mutex.Test) = NULL) cout Open Mutex error! endl; WaitForSingleObject(hMutex,INFINITE);cout ThreadProc: ThreadNumberTemp is
26、 running! endl;cout ThreadProc ThreadNumberTemp gets the mutex endl;ReleaseMutex(hMutex);CloseHandle(hMutex);return 0;39int main(int argc, char* argv )int i;DWORD IDTHREAD_INSTANCE_NUMBER; HANDLE hTHREAD_INSTANCE_NUMBER;HANDLE hMutex;if ( (hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, Mutex.Test) = NU
27、LL) if (hMutex = CreateMutex(NULL, FALSE, Mutex.Test) = NULL ) cout Create Mutex error! endl;return 0; 40 for (i=0;iTHREAD_INSTANCE_NUMBER;i+)WaitForSingleObject(hMutex,INFINITE); hi = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadProc, (void *)&IDi, 0, &(IDi); if (hi = NULL)cout CreateThread
28、 error IDi endl;elsecout CreateThread: IDi endl; ReleaseMutex(hMutex);WaitForMultipleObjects(THREAD_INSTANCE_NUMBER,h,TRUE,INFINITE);cout Close the Mutex Handle! endl;CloseHandle(hMutex);return 0;41程序运行结果: CreateThread: 1796 ThreadProc: 1796 is running! ThreadProc 1796 gets the mutex CreateThread: 2
29、140 ThreadProc: 2140 is running! ThreadProc 2140 gets the mutex CreateThread: 2448 ThreadProc: 2448 is running! ThreadProc 2448 gets the mutex Close the Mutex Handle!42信号量信号量是一个核心对象,拥有一个计数器,可用来管 理大量有限的系统资源当计数值大于零时,信号量为有信号状态当计数值为零时,信号量处于无信号状态43信号量创建信号量HANDLE CreateSemaphore ( PSECURITY_ATTRIBUTE psa,
30、 LONG lInitialCount, /初始计数 LONG lMaximumCount, /最大值 PCTSTR pszName); /信号量对象名称44信号量打开信号量HANDLE OpenSemaphore ( DWORD fdwAccess, BOOL bInherithandle, PCTSTR pszName );参数含义参考互斥量45信号量释放信号量BOOL WINAPI ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, /信号量的当前资源数增加lReleaseCount LPLONG lpPreviousCoun
31、t);46使用信号量同步线程的实例#define THREAD_INSTANCE_NUMBER 3DWORD foo(void * pData) int ThreadNumberTemp = (*(int*) pData);HANDLE hSemaphore;if (hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, Semaphore.Test) = NULL) cout Open Semaphore error! endl; WaitForSingleObject(hSemaphore,INFINITE); cout foo: T
32、hreadNumberTemp is running! endl;cout foo ThreadNumberTemp gets the semaphore endl;ReleaseSemaphore(hSemaphore, 1, NULL);CloseHandle(hSemaphore);return 0;47int main(int argc, char* argv )int i;DWORD ThreadIDTHREAD_INSTANCE_NUMBER; HANDLE hThreadTHREAD_INSTANCE_NUMBER;HANDLE hSemaphore;if (hSemaphore
33、 = CreateSemaphore(NULL,1,1, Semaphore.Test) = NULL ) cout Create Semaphore error! endl;return 0;48 for (i=0;iTHREAD_INSTANCE_NUMBER;i+) WaitForSingleObject(hSemaphore,INFINITE);hThreadi = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) foo, (void *)&ThreadIDi, 0, &(ThreadIDi); if (hThreadi = NULL)co
34、ut CreateThread error ThreadIDi endl;elsecout CreateThread: ThreadIDi endl; ReleaseSemaphore(hSemaphore, 1, NULL);WaitForMultipleObjects(THREAD_INSTANCE_NUMBER,hThread,TRUE,INFINITE);cout Close the Semaphore Handle! = iHigh) return 1; long pivot = ArrayiLow; int iLowSaved = iLow; int iHighSaved = iH
35、igh; while (iLow = pivot & iHigh iLow) iHigh -; ArrayiLow = ArrayiHigh; while (ArrayiLow pivot & iLow iHigh) iLow+; ArrayiHigh = ArrayiLow; ArrayiLow = pivot; QuickSort(Array,iLowSaved,iHigh-1); QuickSort(Array, iLow+1, iHighSaved); return 0; 54UINT DataProcess(LPVOID p) long* Array = (long*)p; char
36、 pszMsg512; memset(pszMsg,0,512); DWORD dwRet; int i; QuickSort( Array, 0, 7); dwRet = WaitForSingleObject(g_hBusy, INFINITE) for(i=0; i8; i+) sprintf(pszMsg, %d , Arrayi); SendMessage(hwnd, EM_REPLACESEL, true, (LPARAM)(pszMsg); Sleep(100); sprintf(pszMsg, rn); SendMessage(hwnd, EM_REPLACESEL, true
37、, (LPARAM)(pszMsg); ReleaseSemaphore(g_hBusy, 1, NULL); return 0;55运行的主要代码:g_hBusy = CreateSemaphore(NULL, 1, 1, NULL);/创建信号量hwnd=GetEditCtrl().GetSafeHwnd();创建四个线程:AfxBeginThread(DataProcess, (LPVOID)data1, THREAD_PRIORITY_NORMAL);AfxBeginThread(DataProcess, (LPVOID)data2, THREAD_PRIORITY_NORMAL);A
38、fxBeginThread(DataProcess, (LPVOID)data3, THREAD_PRIORITY_NORMAL);AfxBeginThread(DataProcess, (LPVOID)data4, THREAD_PRIORITY_NORMAL); 56运行结果:12 32 42 43 47 75 86 763 36 46 47 68 73 84 432 732 37 48 78 326 435 754 765 785 34 50 54 76 93 94 456 457不使用信号量(程序中去掉WaitForSingleObject()和ReleaseSemaphore()函数
39、)的运行结果之一:12 36 37 34 32 46 48 50 42 47 78 54 43 68 326 76 47 73 435 93 75 84 754 94 86 432 765 456 763 732 785 45757MFC中实现线程同步的方法基本和Win32的实现方法相同 .Net Framework线程同步 .NET应用程序是基于.NET框架的CLR是.NET框架的重要组成部分CLR是支持多线程的所有.NET应用程序都可以实现多线程可使用VB.NET或者C#.NET框架的语言来设计多线程程序 ,以Visual C#.NET为例 System.Threading命名空间下包含了
40、在.NET框架中进行多线程编程所需要的类,因此在程序中首先要声明程序位于System.Threading命名空间。5859.Net Framework线程同步的实现创建辅助(或从属)线程的第一个步骤是创建 ThreadStart 代理,指定要由该线程执行的线程函数。然后将 ThreadStart 代理传递给 Thread 类的构造函数。ThreadStart starter = new ThreadStart ( MyFunction ); Thread t = new Thread ( starter ); t.Start();线程创建后,可以使用Thread类的方法对线程进行控制:Resu
41、me 继续已挂起的线程。 Sleep 已重载。 将当前线程阻塞指定的毫秒数。 Suspend 挂起线程,或者如果线程已挂起,则不起作用。 Abort 调用此方法通常会终止线程。 实例(来源于MSDN )using System;using System.Threading;class Test static void Main() ThreadStart threadDelegate = new ThreadStart(Work.DoWork); Thread newThread = new Thread(threadDelegate); newThread.Start(); Work w =
42、 new Work(); w.Data = 42; threadDelegate = new ThreadStart(w.DoMoreWork); newThread = new Thread(threadDelegate); newThread.Start(); class Work public static void DoWork() Console.WriteLine(Static thread procedure.); public int Data; public void DoMoreWork() Console.WriteLine(Instance thread procedu
43、re. Data=0, Data); 60.NET framework提供了很多的类和数据类型来控制对共享资源的访问。常用的类有:Monitor Class:Monitor 类非常适合于在给定的时间和指定的代码段只能被一个线程访问情况下的线程同步。WaitHandle Class:作为基类来使用,它允许多个等待操作。这个类封装了win32的同步处理方法。WaitHandle对象通知其他的线程它需要对资源排他性的访问,其他的线程必须等待,直到WaitHandle不再使用资源和等待句柄没有被使用。Mutex Class :Mutex允许一个线程独占共享资源的同时阻止其他线程和进程的访问。61Aut
44、oResetEvent Class:这个类可以通知一个或多个线程发生事件。ManualResetEvent Class:这个类也用来通知一个或多个线程事件发生了。它的状态可以手动的被设置和重置。Interlocked Class:提供了在线程之间共享的变量访问的同步,它的操作是原子操作,且被线程共享。 ReaderWriterLock class:它定义了一种锁,提供唯一写/多读的机制,使得读写的同步lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:Object thisLock = new Object();lock (thisLoc
45、k) / Critical code section银行取款实例 using System;using System.Threading;class Test static int total = 100; public static void WithDraw1( ) int n=90; if (n = total) total -= n; Console.WriteLine(You have withdrawn. n=0, n); Console.WriteLine(total=0, total); else Console.WriteLine(You do not enough mone
46、y. n=0, n); Console.WriteLine(total=0, total); 64 public static void WithDraw2( ) int n = 20; if (n = total) total -= n; Console.WriteLine(You have withdrawn. n=0, n); Console.WriteLine(total=0, total); else Console.WriteLine(You do not enough money. n=0, n); Console.WriteLine(total=0, total); publi
47、c static void Main( ) ThreadStart thread1 = new ThreadStart(WithDraw1); Thread newThread1 = new Thread(thread1); ThreadStart thread2 = new ThreadStart(WithDraw2); Thread newThread2 = new Thread(thread2); newThread1.Start(); newThread2.Start(); 65分析当某个线程调用WithDraw1方法时,这时的total值为100,而正当要减去90的时候,另外一个线程
48、调用了WithDraw2,它要减去20,结果total减去了20,然后又在原先total =100的值的情况下减掉了90,最后的结果是total被减去了110,出现了错误的操作。同样,很明显Add方法和Delete方法也是不能同时被调用的,所以必须进行线程同步处理66简单的方法是用lock语句lock (lock_total) if (n = total) total -= n; Console.WriteLine(You have withdrawn. n=0, n); Console.WriteLine(total=0, total); else Console.WriteLine(You
49、 do not enough money. n=0, n); Console.WriteLine(total=0, total); 也可以使用Monitor类的方法基本一样:Monitor.Enter(monitor_total) if (n = total) total -= n; Console.WriteLine(You have withdrawn. n=0, n); Console.WriteLine(total=0, total); else Console.WriteLine(You do not enough money. n=0, n); Console.WriteLine(
50、total=0, total); Monitor.Exit(monitor_total)也可以使用Mutex以及其他同步机制来实现线程间同步的目的 大家试一试!684.4 多线程调试与优化 Visual Studio调试器: 可以观察程序运行状态,确定错误位置 可以中断程序执行,检查代码 计算和编辑程序中的变量,查看寄存器和内存 可以在调试时修改代码,然后继续执行69MSDN中给出的使用Visual Studio 调试器调试线程的一些提示和一些常见的问题 在多线程代码中,使用跟踪点可以检查出程序中的许多bug。可以使用断点筛选器将断点置于单个线程上。如果我们通过用户界面来调试多线程应用程序可能
51、比较困难,那么可以考虑在另一台机器上运行应用程序并使用远程调试。可以在本机代码中使用 SetThreadName API 或在托管代码中使用 Name 属性来设置线程名称。线程名称对于托管代码特别有用,因为在托管代码中无法通过线程 ID 来识别线程。多线程应用程序中的死锁是一类极其严重的 bug 。70在调试本机代码时,可以通过在“监视”窗口或“快速监视”对话框中输入 TIB 查看“线程信息块”的内容。调试本机代码时,在“监视”窗口或“快速监视”对话框中输入 Err,可以查看当前线程的错误代码。在调试使用了本机代码对托管代码调用的混合代码时,托管代码与调用它的本机代码在相同的物理线程内运行,挂
52、起或冻结本机线程也会冻结托管代码。我们还可以使用 C 运行时库 (CRT) 函数来调试多线程应用程序。71调试器中的数据 DataTips数据提示是一种在调试过程中查看程序中某一变量和对象的有关信息的工具。在调试器处于中断模式下,可以查看当前范围内变量的值数据提示是用于在调试过程中查看程序中的变量和对象的有关信息的最方便工具之一。在调试器处于中断模式时,可以将鼠标指针置于源窗口中的变量上,这样就可以在当前范围内查看变量的值可视化工具可视化工具是 Visual Studio 调试器的新组件,通过它可以以我们指定的方式查看对象或变量的内容。例如,可以使用 HTML 可视化工具来查看 HTML 字符串。可以通过数据提示、“监视”窗口、“自动”窗口、“局部变量”窗口或“快速监视”对话框来访问可视化工具。变量窗口可以通过变量窗口来查看变量、寄存器内容和表达式等。72跟踪点/断点 73跟踪点用户自定义操作的断点,它和断点相关联当命中跟踪点时,跟踪点会使调试器执行指定的操作,而不是或不仅
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 停车场系统维修外包合同
- 冻结法隧道施工工艺及施工方法
- 公园物业管理外包合同
- 2026年职业健康培训考试试题及答案
- 公司让离职签给外包合同
- 腔镜手术基本操作及相关知识试题与答案
- 雨期基坑施工工艺
- 旅馆从业在线考试题及答案解析
- 麻醉科主治医师考试(疼痛诊疗学及危重病医学)试题及答案
- 口唇破溃护理
- 做账实操-财务交接及半路建账实操SOP
- 未成年人家庭监护能力评估通知书、参考指标、评估报告(参考)
- 学校结构化面试试题及答案
- 考叉车证科目一模拟试题
- 2025年江苏省苏州市工业园区事业单位招聘考试综合类专业能力测试试卷及答案
- 串串店加盟易合同范本
- 诚信管理体系知识培训课件
- 戚继光马上作课件
- 2025年中国花岗岩石材数据监测报告
- 临床试验SAE培训课件
- 人工智能应用技术基础 课件 项目七 解码人工智能生成内容AIGC的独特技术
评论
0/150
提交评论