线程函数必须是全局函数
如果一定要是对话框类的一个成员函数,可以声明为静态成员函数

解决方案 »

  1.   

    3. 如何使用CreateThread函数?
    当CreateThread被调用时,系统创建一个线程内核对象。该线程内核对象不是线程本身,而是操作系统用来管理线程的较小的数据结构。使用时应当注意在不需要对线程内核进行访问后调用CloseHandle函数关闭线程句柄。因为CreateThread函数中使用某些C/C++运行期库函数时会有内存泄漏,所以应当尽量避免使用。
    参数 含义
    lpThreadAttributes 如果传递NULL该线程使用默认安全属性。如果希望所有的子进程能够继承该线程对象的句柄,必须将它的bInheritHandle成员被初始化为TRUE。
    dwStackSize 设定线程堆栈的地址空间。如果非0,函数将所有的存储器保留并分配给线程的堆栈。如果是0,CreateThread就保留一个区域,并且将链接程序嵌入.exe文件的/STACK链接程序开关信息指明的存储器容量分配给线程堆栈。
    lpStartAddress 线程函数的地址。
    lpParameter 传递给线程函数的参数。
    dwCreationFlags 如果是0,线程创建后立即进行调度。如果是CREATE_SUSPENDED,系统对它进行初始化后暂停该线程的运行。
    LpThreadId 用来存放系统分配给新线程的ID。
    4. 如何终止线程的运行?
    (1) 线程函数返回(最好使用这种方法)。
    这是确保所有线程资源被正确地清除的唯一办法。
    如果线程能够返回,就可以确保下列事项的实现:
    •在线程函数中创建的所有C++对象均将通过它们的撤消函数正确地撤消。
    •操作系统将正确地释放线程堆栈使用的内存。
    •系统将线程的退出代码设置为线程函数的返回值。
    •系统将递减线程内核对象的使用计数。
    (2) 调用ExitThread函数(最好不要使用这种方法)。
    该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。
    (3) 调用TerminateThread函数(应该避免使用这种方法)。
    TerminateThread能撤消任何线程。线程的内核对象的使用计数也被递减。TerminateThread函数是异步运行的函数。如果要确切地知道该线程已经终止运行,必须调用WaitForSingleObject或者类似的函数。当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。
    (4) 包含线程的进程终止运行(应该避免使用这种方法)。
    由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。就像从每个剩余的线程调用TerminateThread一样。这意味着正确的应用程序清除没有发生,即C++对象撤消函数没有被调用,数据没有转至磁盘等等。
    一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用GetExitcodeThread来检查由hThread标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码。
    5. 为什么不要使用_beginthread函数和_endthread函数?
    与_beginthreadex函数相比参数少,限制多。无法创建暂停的线程,无法取得线程ID。_endthread函数无参数,线程退出代码必须为0。还有_endthread函数内部关闭了线程的句柄,一旦退出将不能正确访问线程句柄。
    6. 如何对进程或线程的内核进行引用?
    HANDLE GetCurrentProcess(  );
    HANDLE GetCurrentThread(  );
    这两个函数都能返回调用线程的进程的伪句柄或线程内核对象的伪句柄。伪句柄只能在当前的进程或线程中使用,在其它线程或进程将不能访问。函数并不在创建进程的句柄表中创建新句柄。调用这些函数对进程或线程内核对象的使用计数没有任何影响。如果调用CloseHandle,将伪句柄作为参数来传递,那么CloseHandle就会忽略该函数的调用并返回FALSE。
    DWORD GetCurrentProcessId(  );
    DWORD GetCurrentThreadId(  );
    这两个函数使得线程能够查询它的进程的唯一ID或它自己的唯一ID。
    7. 如何将伪句柄转换为实句柄?
    HANDLE hProcessFalse = NULL;
    HANDLE hProcessTrue = NULL;
    HANDLE hThreadFalse = NULL;
    HANDLE hThreadTrue = NULL;hProcessFalse = GetCurrentProcess(  );
    hThreadFalse = GetCurrentThread(  );
    取得线程实句柄:
    DuplicateHandle( hProcessFalse, hThreadFalse, hProcessFalse, &hThreadTrue, 0, FALSE, DUPLICATE_SAME_ACCESS );
    取得进程实句柄:
    DuplicateHandle( hProcessFalse, hProcessFalse, hProcessFalse, &hProcessTrue, 0, FALSE, DUPLICATE_SAME_ACCESS );
    由于DuplicateHandle会递增特定对象的使用计数,因此当完成对复制对象句柄的使用时,应该将目标句柄传递给CloseHandle,从而递减对象的使用计数。
    8. 在一个进程中可创建线程的最大数是得多少?
    线程的最大数取决于该系统的可用虚拟内存的大小。默认每个线程最多可拥有至多1MB大小的栈的空间。所以,至多可创建2028个线程。如果减少默认堆栈的大小,则可以创建更多的线程。
      

  2.   

    楼上的哥哥们手真快,呵呵……刷的一下就贴上一大堆文字上去了……哪里弄的?