⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfc教程_ mfc的进程和线程.htm

📁 MFC的教程。 包括: MFC教程_ 概述.files MFC教程_ MFC和Win32.files MFC教程_ CObject类.files MFC教程_ 消息映射的实现.files
💻 HTM
📖 第 1 页 / 共 3 页
字号:
to 
DLL),DllMain给它分配动态内存并且使用TlsSetValue把线程私有的数据按索引保存。DLL函数可以使用TlsGetValue按索引读取调用线程的私有数据。</P>
<P align=justify>TLS函数如下:</P>
<UL>
  <P align=justify>
  <LI>DWORD TlsAlloc() 
  <P></P></LI></UL>
<P align=justify>在进程或DLL初始化时调用,并且把返回值(索引值)作为全局变量保存。</P>
<UL>
  <P align=justify>
  <LI>BOOL TlsSetValue( 
  <P></P></LI></UL>
<DIR>
<P align=justify>DWORD dwTlsIndex, //TLS index to set value for </P>
<P align=justify>LPVOID lpTlsValue //value to be stored </P></DIR>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>dwTlsIndex是TlsAlloc分配的索引。</P>
<P align=justify>lpTlsValue是线程在TLS槽中存放的数据指针,指针指向线程要保存的数据。</P>
<P align=justify>线程首先分配动态内存并保存数据到此内存中,然后调用TlsSetValue保存内存指针到TLS槽。</P>
<UL>
  <P align=justify>
  <LI>LPVOID TlsGetValue( 
  <P></P></LI></UL>
<P align=justify>DWORD dwTlsIndex // TLS index to retrieve value for</P>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>dwTlsIndex是TlsAlloc分配的索引。</P>
<P align=justify>当要存取保存的数据时,使用索引得到数据指针。</P>
<UL>
  <P align=justify>
  <LI>BOOL TlsFree( 
  <P></P></LI></UL>
<P align=justify>DWORD dwTlsIndex // TLS index to free</P>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>dwTlsIndex是TlsAlloc分配的索引。</P>
<P align=justify>当每一个线程都不再使用局部存储数据时,线程释放它分配的动态内存。在TLS索引不再需要时,使用TlsFree释放索引。</P>
<OL>
  <OL>
    <P align=justify>
    <LI><A name=_Toc445889085></A><A name=_Toc445782488></A><A 
    name=_Toc452640949></A><A name=_Toc457299047></A><B>线程同步</B> 
    <P></P>
    <P 
    align=justify>同步可以保证在一个时间内只有一个线程对某个资源(如操作系统资源等共享资源)有控制权。共享资源包括全局变量、公共数据成员或者句柄等。同步还可以使得有关联交互作用的代码按一定的顺序执行。</P>
    <P align=justify>Win32提供了一组对象用来实现多线程的同步。</P>
    <P align=justify>这些对象有两种状态:获得信号(Signaled)或者没有或则信号(Not signaled)。线程通过Win32 
    API提供的同步等待函数(Wait 
    functions)来使用同步对象。一个同步对象在同步等待函数调用时被指定,调用同步函数地线程被阻塞(blocked),直到同步对象获得信号。被阻塞的线程不占用CPU时间。</P>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445889086></A><A name=_Toc445782489></A><A 
      name=_Toc452640950></A><A name=_Toc457299048></A><B>同步对象</B> 
      <P></P></LI></OL></LI></OL></OL>
<P 
align=justify>同步对象有:Critical_section(关键段),Event(事件),Mutex(互斥对象),Semaphores(信号量)。</P>
<P align=justify>下面,解释怎么使用这些同步对象。</P>
<OL>
  <P align=justify>
  <LI>关键段对象: 
  <P></P>
  <P align=justify>首先,定义一个关键段对象cs:</P>
  <P align=justify>CRITICAL_SECTION cs;</P>
  <P align=justify>然后,初始化该对象。初始化时把对象设置为NOT_SINGALED,表示允许线程使用资源:</P>
  <P align=justify>InitializeCriticalSection(&amp;cs);</P>
  <P 
  align=justify>如果一段程序代码需要对某个资源进行同步保护,则这是一段关键段代码。在进入该关键段代码前调用EnterCriticalSection函数,这样,其他线程都不能执行该段代码,若它们试图执行就会被阻塞。</P>
  <P 
  align=justify>完成关键段的执行之后,调用LeaveCriticalSection函数,其他的线程就可以继续执行该段代码。如果该函数不被调用,则其他线程将无限期的等待。</P>
  <P align=justify></P>
  <LI>事件对象 
  <P></P>
  <P 
  align=justify>首先,调用CreateEvent函数创建一个事件对象,该函数返回一个事件句柄。然后,可以设置(SetEvent)或者复位(ResetEvent)一个事件对象,也可以发一个事件脉冲(PlusEvent),即设置一个事件对象,然后复位它。复位有两种形式:自动复位和人工复位。在创建事件对象时指定复位形式。。</P>
  <P 
  align=justify>自动复位:当对象获得信号后,就释放下一个可用线程(优先级别最高的线程;如果优先级别相同,则等待队列中的第一个线程被释放)。</P>
  <P align=justify>人工复位:当对象获得信号后,就释放所有可利用线程。</P>
  <P align=justify>最后,使用CloseHandle销毁创建的事件对象。</P>
  <P align=justify></P>
  <LI>互斥对象 
  <P></P>
  <P 
  align=justify>首先,调用CreateMutex创建互斥对象;然后,调用等待函数,可以的话利用关键资源;最后,调用RealseMutex释放互斥对象。</P>
  <P align=justify>互斥对象可以在进程间使用,但关键段对象只能用于同一进程的线程之间。</P>
  <P align=justify></P>
  <LI>信号量对象 
  <P></P>
  <P align=justify>在Win32中,信号量的数值变为0时给以信号。在有多个资源需要管理时可以使用信号量对象。</P>
  <P 
  align=justify>首先,调用CreateSemaphore创建一个信号量;然后,调用等待函数,如果允许的话,则利用关键资源;最后,调用RealeaseSemaphore释放信号量对象。</P>
  <P align=justify></P>
  <LI>此外,还有其他句柄可以用来同步线程: 
  <P></P></LI></OL>
<P align=justify>文件句柄(FILE HANDLES)</P>
<P align=justify>命名管道句柄(NAMED PIPE HANDELS)</P>
<P align=justify>控制台输入缓冲区句柄(CONSOLE INPUT BUFFER HANDLES)</P>
<P align=justify>通讯设备句柄(COMMUNICTION DEVICE HANDLES)</P>
<P align=justify>进程句柄(PROCESS HANDLES)</P>
<P align=justify>线程句柄(THREAD HANDLES)</P>
<P align=justify>例如,当一个进程或线程结束时,进程或线程句柄获得信号,等待该进程或者线程结束的线程被释放。</P>
<OL>
  <OL>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445889087></A><A name=_Toc445782490></A><A 
      name=_Toc452640951></A><A name=_Toc457299049></A><B>等待函数</B> 
      <P></P></LI></OL></OL></OL>
<P align=justify>Win32提供了一组等待函数用来让一个线程阻塞自己的执行。等待函数分三类:</P>
<OL>
  <P align=justify>
  <LI>等待单个对象的(FOR SINGLE OBJECT): 
  <P></P>
  <P align=justify>这类函数包括:</P>
  <P align=justify>SignalObjectAndWait</P>
  <P align=justify>WaitForSingleObject</P>
  <P align=justify>WaitForSingleObjectEx</P>
  <P align=justify>函数参数包括同步对象的句柄和等待时间等。</P>
  <P align=justify>在以下情况下等待函数返回:</P>
  <P align=justify>同步对象获得信号时返回;</P>
  <P 
  align=justify>等待时间达到了返回:如果等待时间不限制(Infinite),则只有同步对象获得信号才返回;如果等待时间为0,则在测试了同步对象的状态之后马上返回。</P>
  <P align=justify></P>
  <LI>等待多个对象的(FOR MULTIPLE OBJECTS) 
  <P></P>
  <P align=justify>这类函数包括:</P>
  <P align=justify>WaitForMultipleObjects</P>
  <P align=justify>WaitForMultipleObjectsEx</P>
  <P align=justify>MsgWaitForMultipleObjects</P>
  <P align=justify>MsgWaitForMultipleObjectsEx</P>
  <P align=justify>函数参数包括同步对象的句柄,等待时间,是等待一个还是多个同步对象等等。</P>
  <P align=justify>在以下情况下等待函数返回:</P>
  <P align=justify>一个或全部同步对象获得信号时返回(在参数中指定是等待一个或多个同步对象);</P>
  <P 
  align=justify>等待时间达到了返回:如果等待时间不限制(Infinite),则只有同步对象获得信号才返回;如果等待时间为0,则在测试了同步对象的状态之后马上返回。</P>
  <P align=justify></P>
  <LI>可以发出提示的函数(ALTERABLE) 
  <P></P></LI></OL>
<P align=justify>这类函数包括:</P>
<P align=justify>MsgWaitForMultipleObjectsEx</P>
<P align=justify>SignalObjectAndWait</P>
<P align=justify>WaitForMultipleObjectsEx</P>
<P align=justify>WaitForSingleObjectEx</P>
<P align=justify>这些函数主要用于重叠(Overlapped)的I/O(异步I/O)。</P>
<OL>
  <OL>
    <P align=justify>
    <LI><A name=_Toc445889088></A><A name=_Toc445782491></A><A 
    name=_Toc452640952></A><A name=_Toc457299050></A><B>MFC的线程处理</B> 
    <P></P>
    <P align=justify>在Win32 
    API的基础之上,MFC提供了处理线程的类和函数。处理线程的类是CWinThread,函数是AfxBeginThread、AfxEndThread等。</P>
    <P align=justify>表5-6解释了CWinThread的成员变量和函数。</P>
    <P 
    align=justify>CWinThread是MFC线程类,它的成员变量m_hThread和m_hThreadID是对应的Win32线程句柄和线程ID。</P>
    <P align=justify>MFC明确区分两种线程:用户界面线程(User interface thread)和工作者线程(Worker 
    thread)。用户界面线程一般用于处理用户输入并对用户产生的事件和消息作出应答。工作者线程用于完成不要求用户输入的任务,如耗时计算。</P>
    <P align=justify>Win32 
    API并不区分线程类型,它只需要知道线程的开始地址以便它开始执行线程。MFC为用户界面线程特别地提供消息泵来处理用户界面的事件。CWinApp对象是用户界面线程对象的一个例子,CWinApp从类CWinThread派生并处理用户产生的事件和消息。</P>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445889089></A><A name=_Toc445782492></A><A 
      name=_Toc452640953></A><A name=_Toc457299051></A><B>创建用户界面线程</B> 
      <P></P></LI></OL></LI></OL></OL>
<P align=justify>通过以下步骤创建一个用户界面线程:</P>
<UL>
  <P align=justify>
  <LI>从CWinThread派生一个有动态创建能力的类。使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏来支持动态创建。 
  <P></P>
  <P align=justify></P>
  <LI>覆盖CWinThread的一些虚拟函数,可以覆盖的函数见表5-4关于CWinThread的部分。其中,函数InitInstance是必须覆盖的,ExitInstance通常是要覆盖的。 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -