精华内容
下载资源
问答
  • 常见的核心对象有一下几种: 进程(Process) 线程(Thread) 文件(File) 事件(Event) 信号量(Semaphore) 互斥体(Mutex) 管道(Named Pipe) 匿名管道(Anonymous Pipe) BOOL CloseHandle(HANDLE hObj);...

    1.
    HANDLE WINAPI CreateThread(
    __in          LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in          SIZE_T dwStackSize,
    __in          LPTHREAD_START_ROUTINE lpStartAddress,
    __in          LPVOID lpParameter,
    __in          DWORD dwCreationFlags,
    __out         LPDWORD lpThreadId
    );

    lpThreadAttributes 用来描述新创建线程的security属性,通常情况下传NULL,即默认属性
    dwStackSize 指示线程拥有的堆栈的大小,0代表默认值1M
    lpStartAddress 应该传一个函数的指针,该函数不能是类成员函数(static 成员函数除外)
    LPTHREAD_START_ROUTINE 定义如下:
    typedef DWORD(WINAPI* PTHREAD_START_ROUTINE)
    (
    LPVOID lpThreadParameter
    );
    thpedef PTHREAD_START_ROUNTINE LPTHREAD_START_ROUTINE;
    该指针函数必须是下面格式:
    DWORD _stdcall fun(LPVOID lpThreadParameter);
    lpParameter 只是传递给新线程入口函数的参数
    dwCreationFlags 指示以何种方式创建新的线程,默认值0表示创建后立即运行该线程,
    传递CREATE_SUSPENDED 表示创建一个挂起状态的新线程。
    lpThreadId 用来保存新线程的ID。在WinNT操作系统上,可以设置为NULL,表示不需要该ID。
    该函数的返回值是一个HANDLE类型的值,代表这个新的线程,使用这个值可以完成许多
    其他针对该线程的操作。

    VOID ExitThread(DWORD dwExitCode);
    该函数接受一个整数值作为线程的返回值,该函数只能在线程内部使用,也就是“自己关闭自己”,
    如果在一个线程的外部关闭该线程,需要其他函数的帮忙。


    2.下面的这俩函数其实调用了CreateThread 与ExitThread
    unsigned long _cdecl _beginthreadex
    (void *,
    unsigned,
    unsigned(_stdcall *) (void *),
    void *,
    unsigned,
    unsigned*);

    void _cdecl _endthreadex(unsigned);

    3.AfxBeginThread /AfxEndThread

    VC 6.0 创建线程的三种方法
    1.CreateThread/ExitThread
    2._beginthreadex/_endthreadex
    3.AfxBeginThread /AfxEndThread

    对以上三种方式的选择:
    1.在使用了MFC的程序中使用AfxBeginThread函数或者CWinThread::CreateThread函数创建线程。
    2.在非MFC工程中,如果要创建多线程,建议使用_beginthreadex
    3.避免使用CreateThread函数。不使用_beginthread.
    4.线程内部退出函数使用与创建函数配套的函数。
    对于高手,参照以下几点:(不推荐)
    1.在MFC工程中,如果确定线程中不涉及MFC函数、变量等,可以不适用AfxBeginThread函数或者

    CWinThread::CreateThread函数创建。
    2.在非MFC中,如果确定函数不调用任何C运行时库函数,可以使用CreateThread


    在Windows操作系统上,线程的优先级由低到高被分为32级,用数字0~31来表示,一个
    线程的最终"优先级"是由线程本身的优先级和该线程所属的进程的优先级,以及操作系统对其
    的调整3中因素共同决定的。

    优先权类别(Priority Class)指的是线程所在进程的优先权属性,以数字表示。
    优先权类别:
    IDLE_PRIORITY_CLASS
    NORMAL_PRIORITY_CLASS
    HIGH_PRIORITY_CLASS
    REALTIME_PRIORITY_CLASS

    一般进程的优先权类别都为NORMAL_PRIORITY_CLASS 可以调用
    SetPriorityClass 和 GetPriorityClass 来设置或者获取进程的优先权级别

    BOOL SetPriorityClass(HANDLE hProcess,DWORD dwPriorityClass);
    DWORD GetPriorityClass(HANDLE hProcess);
    hProcess 代表某个进程的句柄。
    dwPriorityClass 为以上4个级别的一个。


    优先权层级是指线程的优先级,作为对所在进程的优先权类别的调整,一数字表示。
    这样就可以使得一个进程内部的线程之间可以有不同的优先级。层次有7级:
    THREAD_PRIORITY_IDLE
    THREAD_PRIORITY_LOWEST
    THREAD_PRIORITY_BELOW_NORMAL
    THREAD_PRIORITY_NORMAL
    THREAD_PRIORITY_ABOVE_NORMAL
    THREAD_PRIORITY_HIGHEST
    THREAD_PRIORITY_TIME_CRITICAL

    BOOL SetThreadPriority(HANDLE hThread,int nPriority);
    int GetThreadPriority(HANDLE hThread);
    hThread 为某个线程的句柄
    nPriority 为上述7个级别中的一个

    CWinThread类对以上两个函数进行了封装
    int CWinThread::GetThreadPriority;
    bool CWinThread::SetThreadPriority(int nPriority);


    核心对象
    从编程语言来说,一个核心对象就是一个整数值。用数据类型HANDLE来表示:

    HADNLE 其实就是 void* 类型也是一个指针,在32位Windows平台上就是32位的整数

    对于Windows操作系统来说,一个核心对象所代表的远远不止这些。核心对象其实就是
    一个"对象",代表着某种事务,该对象由操作系统负责管理,围绕某种对象,通常有
    一组API函数负责完成常见的功能。常见的核心对象有一下几种:
    进程(Process)
    线程(Thread)
    文件(File)
    事件(Event)
    信号量(Semaphore)
    互斥体(Mutex)
    管道(Named Pipe)
    匿名管道(Anonymous Pipe)

    BOOL CloseHandle(HANDLE hObj);
    CloseHandle函数的作用是负责释放某个拥有着对核心对象的拥有权(计数减一)

    展开全文
  • 5个目标文件,演示Address EJB的实现 ,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...
  • vc 线程创建关闭(彻底讲解)

    千次阅读 2014-08-12 12:35:39
     本来照例要先介绍线程几种死法,但是考虑到很多Windows程序员经常混淆线程API,搞不清楚到底该用哪个。所以先来说一下两套线程API的问题。  首先,Windows操作系统本身提供了线程创建函数CreateThread 和...

    转载至:http://3140618.blog.163.com/blog/static/7451797201012344827419/

    ★两套API :OS API vs CRT API

      本来照例要先介绍线程的几种死法,但是考虑到很多Windows程序员经常混淆线程API,搞不清楚到底该用哪个。所以先来说一下两套线程API的问题。

      首先,Windows操作系统本身提供了线程的创建函数CreateThread 和销毁函数ExitThread 。其中的CreateThread 用于创建线程,ExitThread 用于在线程函数内部推出线程(也就是自杀)。

      其次,在Visual C++自带的C运行库(以下简称CRT)中,还带了另外4个API函数,分别是:_beginthread ,_endthread ,_beginthreadex ,_endthreadex 。其中的_beginthread 和_beginthreadex 用于创建线程(它们内部调用了CreateThread ),_endthread 和_endthreadex 用于自杀(它们内部调用了ExitThread )。

      有同学看到这里,被搞懵了,心想:“干嘛要搞这么多玩意儿出来糊弄人?有CreateThread 和ExitThread 不就够了嘛!”其实你有所不知,此中大有奥妙啊。

      因为OS API作为操作系统本身提供的API函数,它被设计为语言无关的。它们不光可以被C++调用,还可以被其它诸如VB、Python、Delphi等开发语言来调用。所以它们不会(也不能够)帮你处理一些和具体编程语言相关的琐事。

      而CRT API虽然最终还是要调用OS API来完成核心的功能,但是CRT API在不知不觉中多帮我们干了一些虽琐碎但重要的工作。(如果同学们想窥探一下CRT API内部都干了些啥,可以拜读一下Win32编程的经典名着《Windows 核心编程》的6.7 章节,里面介绍得挺细致的)

      费了这么多口水,无非是要同学们牢记:以后在Windows平台下开发多线程程序,千万不要 直接使用这两个线程API(也就是CreateThread 和ExitThread ),否则后果自负 :-)

      另外,顺便补充一下。除了上述提到的CRT库。其它一些Windows平台的C++库也可能提供了线程的启动函数(比如MFC的AfxBeginThread),这些函数也对OS API进行了包装,所以用起来也是安全的。

      ★三种死法

      说完了两套API,开始来讨论一下线程的几种死法。线程和进程一样,也有三种死法。详见如下:

      1、自然死亡

      一般来说,每个线程都会对应某个函数(以下称为“线程函数”)。线程函数是线程运行的主体。所谓的“自然死亡”,就是通过return 语句结束线程函数的执行。

      2、自杀

      所谓的“自杀”,就是当前线程通过调用某API把自己 给停掉。前面已经说了OS API的坏话,同学们应该明白不能 再用它们。那我们能否使用CRT API来进行自杀呢?请看MSDN上的相关文档 。上面说了,如果使用_endthread 和_endthreadex ,将导致析构函数不被 调用。

      3、它杀

      所谓的“它杀”,很明显,就是其它线程通过调用某API把当前线程给强行 停掉。对于Windows平台来说,实现“它杀”比较简单,使用TernimateThread 就直接干掉了(它杀也是最野蛮的)。

      ★类对象的析构

      把类对象分为三种:局部非静态对象、局部静态对象、非局部对象。由于非局部对象是在main之前就创建、在进程死亡时析构,暂时与线程扯不上太大关系。剩下的两种局部对象,在宿主线程(所谓宿主线程,就是创建该局部对象的线程)死亡时会受到什么影响捏?请看如下的对照表:

      -------------------------

      局部非静态对象  局部静态对象

      自然死亡    能        能

      自杀     不能       能

      它杀     不能       能

      -------------------------

      从上述结果可以看出,Windows上线程的死法还是以自然死亡为最安全,这点和进程的死法类似。所以同学们在Windows上开发时,要尽量避免自杀和它杀。

      ★关于主线程之死

      所谓“主线程”,就是进程启动时,操作系统为该进程默认创建的第一个线程。通俗地讲,可以把main 函数看成是主线程的线程函数。

      主线程之死是有讲究的。由于前面已经阐述了非自然死亡的坏处,所以我们只讨论主线程自然死亡这一种情况。当主线程自然死亡时(也就是用return 从main 返回时),会导致exit 函数被调用,exit 函数就会开始清除当前进程的各种资源,为进程的死亡作准备。这时候,如果还有其它活着的线程,也会被一起干掉(其效果类似于它杀)。

      为了防止出现上述情况,主线程一定要负责最终的善后工作。务必等到其它线程都死了,它才能死。

    展开全文
  • VC 编程中,若是涉及到多线程编程时,有时我们也需要根据情况获取子线程入口函数的退出码,以便根据具体的程序运行情况做相应的处理。  之前我在使用 VC 开发程序时,也遇到过需要获取子线程入口函数的退出...

           在 VC 编程中,若是涉及到多线程编程时,有时我们也需要根据情况获取子线程入口函数的退出码,以便根据具体的程序运行情况做相应的处理。


           之前我在使用 VC 开发程序时,也遇到过需要获取子线程入口函数的退出码的问题,由于起初没有做过相似的程序,所以只会定义一个全局变量来根据情况,在子线程的入口函数里再为其赋予相应的值。虽然这也是一种方法,但根本不能决定根本的问题,而且若程序中的全局变量定义太多的话又容易造成程序的混乱,但是根据线程入口函数的声明方式,明显是有返回值的,所以我们可以根据它来在主线程直接获取子线程的退出码


           因此我上网搜索了一下,网上基本都说可以通过在主 线程里面直接调用 GetExitCodeThread() 函数来得到子线程入口函数的退出码。

     

           GetExitCodeThread()这个函数确实可以得到子线程入口函数的退出码,但是真要使用它来得倒子线程入口函数的退出码的话是有条件的。我在网上搜多了许久,都没有具体说到这点,很零碎,最后我根据自己的实践,在结合 MSDN 上面的介绍,以及网上的一些资料,终于成功解决的这个问题。以下我就把我的总结归纳一下,以便以后查询时可以用到,同时,也希望能帮到其他同仁们!

     

      首先,GetExitCodeThread()这个函数可以直接得到由 CreateThread() 创建的子线程入口函数的退出码。以下我举个测试的例子吧!

    先创建一个基于MFC的控制台工程,这样比较方便测试。这个不用我来教大家怎么创建吧,呵呵!

    然后在源文件开头,可以在 main 函数外面定义一下变量:

    HANDLE hThread;
    DWORD errCode = 100;

    同时声明子线程入口函数:

    DWORD WINAPI ThreadFunc( LPVOID lpParameter );

     

    接着在特定位置添加以下代码:

    好了,现在就是编写子线程入口函数了,代码如下:


    现在代码编辑工作完成了,然我们测试一下吧,测试效果如下所以:

    看!效果刚刚好,正好是我们在子线程入口函数里面的退出码“8”。

     

     

     

      以上使用 CreateThread() 函数创建的子线程工作的很好,至少能达到我们想要的结果,这是否意味着使用另外三个函数,_beginthread,_beginthreadex与AfxbeginThread也能达到我们需要的效果呢?我们当然希望是,可惜的是,答案是NO,哦,不好意思,_beginthreadex应该可以,读者可以自己测试一下,可是_beginthread和AfxbeginThread创建的子线程就不能那么顺利了。为什么呢?以下我先说明一下具体的原因,然后再说明如何来解决这个问题。

       CreateThreadWindowsAPI函数,提供操作系统级别的创建线程的操作。_beginthread(_beginthreadex)AfxBeginThread的底层实现都调用了CreateThread函数。这是相似之处,但有几个区别之处是值得我们注意的。

      AfxBeginThread里面,CreateThread之后,就CloseHandle了;

      当您使用 _beginthread_endthread时,不要通过调用 Win32 APICloseHandle 显式关闭线程句柄,因为_endthread自动关闭线程句柄;

      当您使用_beginthreadex_endthreadex时,必须通过调用 Win32 APICloseHandle 关闭线程处理, _endthreadex 不关闭线程句柄

      以上这几个地方就是我们应该注意的,现在回到主题,为什么调用GetExitCodeThread()不能正常得到AfxBeginThread和 “_beginthread 与_endthread”的退出码呢,答案就在他们的底层代码自动调用CloseHandle函数。

     

    以下我引用网上一段对CloseHandle()函数的介绍:

    CloseHandle()

      在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

    但是这个handle并不能完全代表这个线程,它仅仅是线程的一个“标识”,系统和用户可以利用它对相应的线程进行必要的操纵。如果在线程成功创建后,不再需要用到这个句柄,就可以在创建成功后,线程退出前直接CloseHandle掉,但这并不会影响到线程的运行。


    不执行CloseHandle() 带来的后果:

      若在线程执行完之后,没有通过CloseHandle()将引用计数减1,在进程执行期间,将会造成内核对象的泄露,相当与句柄泄露,但不同于内存泄露, 这势必会对系统的效率带来一定程度上的负面影响。但是,请记住,当进程结束退出后,系统仍然会自动帮你清理这些资源。但是在这里不推荐这种做法,毕竟不是 一个良好的编程习惯!
    ( 应用程序运行时,有可能泄露内核对象,但是当进程终止运行时,系统能确保所有内容均被正确地清除。另外,这个情况是用于所有对象,资源和内存块,也就是说,当进程终止时,系统将保证不会留下任何对象。)

     

      呵呵,现在知道为什么了吗,啊。。。我也说一下我自己的理解吧,例如,当我们使用AfxBeginThread函数创建一个子线程时,因为等到起子线程运行退出后,该子线程对应的线程句柄也被CloseHandle()函数关闭了,导致其内核资源被系统回收了,所以我们就不能在主线程中调用GetExitCodeThread()函数来得倒子线程的退出码,因为这个函数也需要子线程的句柄作为参数,但此时子线程的内核资源已经被系统回收了,即使我们知道它的句柄也是没用的,也就是说,我们需要在调用GetExitCodeThread()函数之后,再调用CloseHandle()函数,这样才能得到我们需要的子线程函数的退出码。读者若是不信的话,可以使用我们上面使用到的例子:使用CreateThread()创建子线程的例子,把CloseHandle()放置到GetExitCodeThread()函数之前,看看还能不能得到我们想要的退出码。本人在此告诉大家,肯定不可以!呵呵!

     

      好了,现在我们终于知道为什么会这样了,也知道具体原因了,但该如何解决此问题,是不是意味着我们不能再使用GetExitCodeThread()函数来得到AfxBeginThread函数创建的子线程入口函数的退出码了呢?在这里,我跟大家说一下,其实是可以的,哈哈!下面,我就提供几种方法来给大家参考一下!

      我们可以使用以下几个函数来给子线程设置退出码:

      TerminateThread();//msdn及网上很多高手都建议不要使用该函数,再此,本人也建议大家慎用此函数,

                 //想知道原因,哈哈!百度或msdn一下吧!

           ExitThread();

           AfxEndThread();

           _endthreadex();//此函数对应由_beginthreadex() 创建的子线程

           _endthread();//此函数对应由_beginthread() 创建的子线程

     

      以下我就使用AfxBeginThread函数来创建一个子线程来为大家演示一下!

      一开始还是那句话,先创建一个基于MFC的控制台项目,或是使用刚才的那个例子,本人比较懒,呵呵,所以我就在原来的那个例子上面做些改动就行啦!

     

    在源文件开头定义一个变量和一个子线程入口函数:

    CWinThread* thread;

    UINT ThreadProc(LPVOID lpParam);

    接着在main函数的相应位置创建子线程,代码如下:

    子线程入口函数如下:

    好啦,代码已经编写完成啦,接下来该干啥呢,哈哈,迫不及待了吧,那就让我们运行程序试一下咯!

    测试效果就如上所以啦,从中可以看出,退出码为“6”,刚好是我们在子线程入口函数里面设置的退出码!

     

      好啦,介绍了那么多,现在大家应该知道怎么来获取子线程入口函数的退出码了吧!

    其实还有很多地方是需要我们注意的,比方说内存遗漏问题等,但在这里我就不多做介绍啦,相信大家都能够解决的!

     

      希望此篇文章对各位同仁有所帮助!

     

     

    展开全文
  • VC线程安全退出的方法

    千次阅读 2016-05-12 10:05:20
    1. 如果创建线程属于阻塞类型的,比如线程函数中有套接字recv、sendto类似的操作,可能会死等着接收数据,这时想要退出该线程,只能用: BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode ),强行终止该...

    1. 如果创建的线程属于阻塞类型的,比如线程函数中有套接字recv、sendto类似的操作,可能会死等着接收数据,这时想要退出该线程,只能用:

    BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode ),强行终止该线程。

    事实上,也没有好办法了,因为该线程的while循环不“转”了!


    2. 如果创建的线程内while循环能够正常的在“转动”,应该使用下面方法:

    [cpp]  view plain  copy
      在CODE上查看代码片 派生到我的代码片
    1. bool g_bExit = false;  
    2.   
    3. //测试是否安全退出的指针  
    4. unsigned char *buf = NULL;  
    5.   
    6. UINT MyControllingFunction( LPVOID pParam )  
    7. {  
    8.     while(1)  
    9.     {  
    10.         static int k = 0;  
    11.         printf("线程内操作: %d\n", k++);  
    12.         Sleep(2000);  
    13.         if(g_bExit)  
    14.             break;  
    15.     }  
    16.   
    17.     free(buf);  
    18.     buf = NULL;  
    19.     return 1L;  
    20. }  
    21.   
    22.   
    23. using namespace std;  
    24.   
    25. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])  
    26. {  
    27.     int nRetCode = 0;  
    28.   
    29.     // initialize MFC and print and error on failure  
    30.     if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))  
    31.     {  
    32.         // TODO: change error code to suit your needs  
    33.         cerr << _T("Fatal Error: MFC initialization failed") << endl;  
    34.         nRetCode = 1;  
    35.     }  
    36.     else  
    37.     {  
    38.         //创建一个线程  
    39.         CWinThread *pThread = AfxBeginThread(MyControllingFunction, NULL);  
    40.           
    41.         //随便分配一块内存区域  
    42.         buf = (unsigned char *)malloc(1024);  
    43.           
    44.         //主线程  
    45.         while(1)  
    46.         {  
    47.             if(kbhit())  
    48.             {  
    49.                 char ch = getch();  
    50.                 if(ch == 27)//ESC  
    51.                 {  
    52.                     printf("主线程退出\n");  
    53.                     g_bExit = true;  
    54.                     break;  
    55.                 }  
    56.             }  
    57.         }  
    58.       
    59.         //一直等待创建的线程完全退出  
    60.         ::WaitForSingleObject(pThread->m_hThread, INFINITE);  
    61.     }  
    62.   
    63.     return nRetCode;  
    64. }  

    上述代码段的用意是:① 借助一个全局变量通知被创建的线程循环break后退出;② 在主线程使用WaitForSingleObject等待线程结束。

    上述代码段的buf动态内存是模拟了在创建的线程,如果完全退出时,buf会被free释放掉,反之buf会内存泄露。可以注释掉WaitForSingleObject来验证buf是否存在内存泄露。


    线程内Sleep两秒的用意,该线程不是一个完全阻塞线程,但又不是“转动”很快的线程。当主线程的while循环退出后,能观察到::WaitForSingleObject的作用。



    附:

    WaitForSingleObject函数的使用

    等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。

     

    WaitForSingleObject 函数

    DWORD WaitForSingleObject(

    HANDLE hObject,

         DWORD dwMilliseconds

    );

    第一个参数hObject标识一个能够支持被通知/未通知的内核对象(前面列出的任何一种对象都适用)。

    第二个参数dwMilliseconds允许该线程指明,为了等待该对象变为已通知状态,它将等待多长时间。(INFINITE无限时间量,INFINITE已经定义为0xFFFFFFFF(或-1))

    传递INFINITE有些危险如果对象永远变为已通知状态,那么调用线程永远不会被唤醒,它将永远处于死锁状态,不过,它不会浪费宝贵的C P U时间。

     

    例子:

    DWORD dw = WaitForSingleObject(hProcess, 5000);

    switch(dw)

    {

       case WAIT_OBJECT_0:

          // The process terminated.

          break;

     

       case WAIT_TIMEOUT:

          // The process did not terminate within 5000 milliseconds.

          break;

     

       case WAIT_FAILED:

          // Bad call to function (invalid handle?)

          break;

    }

    上面这个代码告诉系统,在特定的进程(hProcess终止运行(进程hProcess终止运行变成已经通知)之前,或者在5000m s时间结束之前,调用线程不应该变为可调度状态。

     WaitForSingleObject的返回值能够指明调用线程为什么再次变为可调度状态。

    如果线程等待的对象变为已通知状态,那么返回值是WAIT_OBJECT_0

    如果设置的超时已经到期,则返回值是WAIT_TIMEOUT

    如果将一个错误的值(如一个无效句柄)传递给WaitForSingleObject,那么返回值将是WAIT_FAILED(若要了解详细信息,可调用GetLastError)。

     

    WaitForMultipleObjects函数

    WaitForMultipleObjects函数与WaitForSingleObject函数很相似,区别在于它允许调用线程同时查看若干个内核对象的已通知状态:

    DWORD WaitForMultipleObjects(

    DWORD dwCount,

       CONST HANDLE* phObjects,

       BOOL fWaitAll,

       DWORD dwMilliseconds

    );

    dwCount参数用于指明想要让函数查看的内核对象的数量。这个值必须1MAXIMU M_WAIT_OBJECTS(在Windows头文件中定义为64)之间。

    phObjects参数是指向内核对象句柄的数组的指针。

     

    可以以两种不同的方式来使用WaitForMultipleObjects函数

    一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态。

    另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态。

    fWaitAll参数告诉该函数,你想要让它使用何种方式。如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行。

    dwMilliseconds参数的作用与它在WaitForSingleObject中的作用完全相同。如果在等待的时候规定的时间到了,那么该函数无论如何都会返回。。

    WaitForMultipleObjects函数的返回值告诉调用线程,为什么它会被重新调度。可能的返回值是WAIT_FAILEDWAIT_TIMEOUT。如果为fWaitAl l参数传递TRUE,同时所有对象均变为已通知状态,那么返回值是WAIT_OBJECT_0。如果为fWaitAll传递FALSE,那么一旦任何一个对象变为已通知状态,该函数便返回。在这种情况下,你可能想要知道哪个对象变为已通知状态。返回值是WAIT_OBJECT_0与(WAIT_OJECT_0 + dwCount-1之间的一个值。换句话说,如果返回值不是WAIT_TIMEOUT,也不是WAIT_FAILED,那么应该从返回值中减去WAIT_OBJECT_0。产生的数字是作为第二个参数传递给WaitForMultipleObjects的句柄数组中的索引。该索引说明哪个对象变为已通知状态。

     

    下面是说明这一情况的一些示例代码

    HANDLE h[3];

    h[0] = hProcess1;

    h[1] = hProcess2;

    h[2] = hProcess3;

    DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000);

    switch(dw)

    {

       case WAIT_FAILED:

          // Bad call to function (invalid handle?)

          break;

     

       case WAIT_TIMEOUT:

          // None of the objects became signaled within 5000 milliseconds.

          break;

     

       case WAIT_OBJECT_0 + 0:

          // The process identified by h[0] (hProcess1) terminated.

          break;

     

       case WAIT_OBJECT_0 + 1:

          // The process identified by h[1] (hProcess2) terminated.

          break;

     

       case WAIT_OBJECT_0 + 2:

          // The process identified by h[2] (hProcess3) terminated.

          break;

    }

    转自http://www.cnblogs.com/fangyukuan/archive/2010/09/03/1817095.html


    展开全文
  • VC线程中控制界面控件的几种方法

    千次阅读 2010-07-30 15:18:00
     为了保证界面的用户体验经常要把数据处理等放到子线程中进行,然后把结果更新到主界面,通常有这样几种方法。  1.启动线程时把控件关联变量的指针传参给线程函数,这种方法无疑是最简单的方法,但极...
  • VC如何创建一个新的线程

    千次阅读 2011-03-17 17:19:00
    AfxBeginThread(DialThread,this);... 随后在线程控制函数中如此这般,调用线程实现函数 _Dial() UINT CRasThread::DialThread(LPVOID pvThread) { // Ï߳̿ØÖƺ¯Êý CRasThread *pThread
  • vc 线程创建关闭

    千次阅读 2010-06-12 13:15:00
     本来照例要先介绍线程几种死法,但是考虑到很多Windows程序员经常混淆线程API,搞不清楚到底该用哪个。所以先来说一下两套线程 API的问题。 首先,Windows操作系统本身提供了线程创建函数CreateThread 和...
  • vc 结束线程

    千次阅读 2012-04-13 13:57:11
    一般情况下,有下面的几种 方法实现这种通信任务:使用全局变量(上一节的例子其实使用的就是这种方法)、使用事件对象、使用消息。这里我们主要介绍后两种方法。 (一) 利用用户定义的消息通信 在...
  • MFC中创建和使用线程的方法

    千次阅读 2019-05-31 10:33:06
    有关创建线程的问题有三方法: 1.C语言函数,调用_beginthread(); 2.API函数,调用CreateThread(); 3.MFC函数,调用AfxBeginThread(); 推荐使用MFC函数AfxBeginThread(); 利用MFC里的AfxBeginThread函数能很方便...
  • 【致谢】http://blog.chinaunix.net/uid-14607221-id-2794653.html 【致谢】... VC创建线程分析 1、CreateThread、_beginthreadex、AfxBeginThread的区别和正确使用: Creat
  • VC创建删除线程

    千次阅读 2010-12-01 23:25:00
    本来照例要先介绍线程几种死法,但是考虑到很多Windows程序员经常混淆线程API,搞不清楚到底该用哪个。所以先来说一下两套线程 API的问题。  首先,Windows操作系统本身提供了线程创建函数...
  • VC++线程函数内怎么调用外部函数

    千次阅读 2013-05-04 16:43:26
    声明:int thread(CProgressCtrl *pro); DWORD WINAPI Fun1Proc(LPVOID lpParameter); void CTestDlg::OnStat() { if (CreateThread(NULL, 0,ListenThreadFunc, ...//把当前窗口指针this,作为函数传递给线程
  • 测试开发笔记

    万次阅读 多人点赞 2019-11-14 17:11:58
    配置管理流程 88 3.SVN实战 88 配置管理工具SVN操作过程手册 90 一、 如何创建“project”项目版本库 90 二、 如何查看创建的“project”项目版本库 95 三、 在版本浏览器里面,创建文件,并进行检出 99 四、 如何对...
  • 带你玩转Visual Studio——VC++的多线程开发

    万次阅读 多人点赞 2016-05-18 23:55:14
    编程思想之多线程与多进程(4)——C++中的多线程一文中讲了VC++的多线程的用法和用例,本文接着这个话题作进一步的讲解:SuspendThread和ResumeThread的用法,线程与同步锁的封装类,及VS中多线程的调试。
  • C++面试题

    千次阅读 多人点赞 2019-01-07 17:06:10
    参数传递具体有哪几种方式?   答:参数传递具体包括:值传递,指针传递和引用传递三种方式。   12. 重载和重写的区别? 答:首先从定义上来说: 重载:是指允许存在多个同名函数,而这些函数的...
  • MFC多线程创建 1.MFC多线程简介 MFC对多线程进行了一层简单的封装,在Visual C++中每个线程都是从CWinThread类继承而来的。每一个应用程序的执行都有一个主线程,这个主线程...利用MFC可以创建种线程,分别
  • C#基础教程-c#实例教程,适合初学者

    万次阅读 多人点赞 2016-08-22 11:13:24
    在C#语言中,同一个类中的函数,如果函数名相同,而参数类型或个数不同,认为是不同的函数,这叫函数重载。仅返回值不同,不能看作不同的函数。这样,可以在类定义中,定义多个构造函数,名字相同,参数类型或个数...
  • VC线程编程

    2015-03-21 09:28:28
    VC线程中需要熟悉的知识点是: 1. 进程和线程的概念;...5. 线程间的通信分为几种,具体怎么实现; 6. 线程之间的同步方式有几种,具体怎么实现; 1. 进程和线程的概念; 程序是计算机指令的集合
  • VC线程中控制界面控件的几种方法

    千次阅读 2010-09-18 21:14:00
    为了保证界面的用户体验经常要把数据处理等放到子线程中进行,然后把结果更新到主界面,通常有这样几种方法。  1.启动线程时把控件关联变量的指针传参给线程函数,这种方法无疑是最简单的方法,但极容易...
  • VC创建线程

    千次阅读 2007-12-06 13:19:00
    另一是不定义类成员函数线程函数,而将线程函数定义为类的友元函数。这样,线程函数也可以有类成员函数同等的权限。本文采用第二方法。 2,编写全局线程函数。  在函数void Proc_WR(LPVOID param)的第一行写入...
  • 在C/C++语言中规定,程序是从main函数开始,也就是C/C++语言中以main函数作为程序的入口,但是操作系统是如何加载这个main函数的呢,程序真正的入口是否是main函数呢?本文主要围绕这个主题,通过逆向的方式来探讨这...
  • VC6.0多线程编程

    千次阅读 2009-08-24 19:43:00
    本文转自:http://hi.baidu.com/gcfxqy/blog/item/26481a080dfb3635e8248854.html#send感谢gcfxqy由于要学习VC方面的多线程实现方法,在网上遇到gcfxgy的博客上的文章,很有用。一、问题的提出编写一个耗时的单线程...
  • vc6.0 线程编程

    千次阅读 2011-07-16 14:02:25
     VC中多线程使用比较广泛而且实用,在网上看到的教程.感觉写的挺好.一、问题的提出编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG
  • VC++多线程函数调用

    千次阅读 2013-05-29 13:59:29
    在VC++中创建线程函数可以用API 或者MFC封装的多线程函数。。   函数原型 MSDN中CreateThread原型: HANDLE CreateThread(  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD  SIZE_T dwStackSize, ...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...
  • vc6多线程-转载

    千次阅读 2011-06-30 09:52:00
    一、问题的提出编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,430
精华内容 8,572
关键字:

vc创建线程的几种函数