• 成员函数做为线程函数


    成员函数做为线程函数

    WIN32线程控制主要实现线程的创建、终止、挂起和恢复等操作,这些操作都依赖于WIN32提供的一组API和具体编译器的C运行时库函数。

    1.线程函数
      在启动一个线程之前,必须为线程编写一个全局的线程函数,这个线程函数接受一个32位的LPVOID作为参数,返回一个UINT,线程函数的结构为:

    UINT ThreadFunction(LPVOID pParam)
    {
     //线程处理代码
     return0;
    }

      在线程处理代码部分通常包括一个死循环,该循环中先等待某事情的发生,再处理相关的工作:

    while(1)
    {
     WaitForSingleObject(…,…);//或WaitForMultipleObjects(…)
     //Do something
    }

      一般来说,C++的类成员函数不能作为线程函数。这是因为在类中定义的成员函数,编译器会给其加上this指针。请看下列程序:

    #include "windows.h"
    #include <process.h>
    class ExampleTask 
    { 
     public: 
      void taskmain(LPVOID param); 
      void StartTask(); 
    }; 
    void ExampleTask::taskmain(LPVOID param) 
    {} 
    void ExampleTask::StartTask() 
    { 
     _beginthread(taskmain,0,NULL);
    } 
    int main(int argc, char* argv[])
    {
     ExampleTask realTimeTask;
     realTimeTask.StartTask();
     return 0;
    } 

      程序编译时出现如下错误:
    error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
    None of the functions with this name in scope match the target type 

      再看下列程序:

    #include "windows.h"
    #include <process.h>
    class ExampleTask 
    { 
     public: 
      void taskmain(LPVOID param); 
    }; 
    void ExampleTask::taskmain(LPVOID param) 
    {} 
    int main(int argc, char* argv[])
    {
     ExampleTask realTimeTask;
     _beginthread(ExampleTask::taskmain,0,NULL);
     return 0;
    }

      程序编译时会出错:

    error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
    None of the functions with this name in scope match the target type 

      如果一定要以类成员函数作为线程函数,通常有如下解决方案:

      (1)将该成员函数声明为static类型,去掉this指针;
      我们将上述二个程序改变为:

    #include"windows.h"
    #include<process.h>
    class ExampleTask 
    { 
     public: 
      void static taskmain(LPVOID param); 
      void StartTask(); 
    }; 
    void ExampleTask::taskmain(LPVOID param) 
    {} 
    void ExampleTask::StartTask() 
    { 
     _beginthread(taskmain,0,NULL);
    } 
    
    int main(int argc, char* argv[])
    {
     ExampleTask realTimeTask;
     realTimeTask.StartTask();
     return 0;
    }

    #include "windows.h"
    #include <process.h>
    class ExampleTask 
    { 
     public: 
      void static taskmain(LPVOID param); 
    }; 
    
    void ExampleTask::taskmain(LPVOID param) 
    {} 
    
    int main(int argc, char* argv[])
    {
     _beginthread(ExampleTask::taskmain,0,NULL);
     return 0;
    }

      均编译通过。

      将成员函数声明为静态虽然可以解决作为线程函数的问题,但是它带来了新的问题,那就是static成员函数只能访问static成员。解决此问题的一种途径是可以在调用类静态成员函数(线程函数)时将this指针作为参数传入,并在改线程函数中用强制类型转换将this转换成指向该类的指针,通过该指针访问非静态成员。

      (2)不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。
    这样,线程函数也可以有类成员函数同等的权限; 
      我们将程序修改为:

    #include “windows.h"
    #include <process.h>
    class ExampleTask 
    { 
     public: 
      friend void taskmain(LPVOID param); 
      void StartTask(); 
    }; 
    void taskmain(LPVOID param) 
    { 
     ExampleTask * pTaskMain = (ExampleTask *) param; 
     //通过pTaskMain指针引用 
    } 
    void ExampleTask::StartTask() 
    { 
     _beginthread(taskmain,0,this);
    }
    
    int main(int argc, char* argv[])
    {
     ExampleTask realTimeTask;
     realTimeTask.StartTask();
     return 0;
    }

    (3)可以对非静态成员函数实现回调,并访问非静态成员,此法涉及到一些高级技巧,在此不再详述。

    链接:http://www.cctry.com/thread-19591-1-1.html

  • 相关阅读:
    wince串口打印信息的屏蔽与打开
    2440 6.0BSP 移植过程之OAL
    2440 6.0BSP移植过程之电池驱动
    2440 6.0BSP移植过程之SD卡驱动
    如何在wince6.0 模拟器上跑以前编译好的EVC MFC程序
    2440 休眠唤醒的实现过程(作者:wogoyixikexie@gliet)
    CETK的使用(USB连接方式)
    如何扩展ARM内存(OEMGetExtensionDRAM和pNKEnumExtensionDRAM函数可以解决问题)
    ZLG7290(wince下)驱动之不停执行同一动作的解决办法(作者:wogoyixikexie@gliet)
    2440 中断优先级问题(作者wogoyixikexie@gliet)
  • 原文地址:https://www.cnblogs.com/jiqiaochun/p/4715500.html
Copyright © 2020-2023  润新知