Win32多线程类

来源:互联网 发布:淘宝网人工客服电话 编辑:程序博客网 时间:2024/05/16 11:50

 

Win32多线程类

       前些时候用CUDA做了个加速三维配准的程序,做的结果很是让人郁闷,在一个四核CPU9600GT显卡上运行的速度差不多,偏偏对方又规定了不能换更高档的显卡,于是决定改用CPU多线程来做并行计算,结果还不错,于是把程序写成了win32多线程的类,封装在DLL中。下面介绍一下怎么写多线程的类,如果有错误的话希望大家指正。

 

       首先是关于Win32多线程的一些基本知识,包括线程创建和同步等,更详细的内容大家可以在清华大学出版社的《多核程序设计》中找到。对多线程编程有过初步了解的可以直接跳过这一部分。

       Win32API中用于创建线程的主要有两个函数,一个是定义在Windows.h中的CreateThread,另外一个是定义在process.h中的_beginthread函数。这里我用的是形式比较简单的_beginthread函数。

线程同步主要以下面几种方式实现:全局变量,事件,临界区,互斥量和信号量,采用哪种方式取决于要用多线程做什么。例如用事件做线程同步的话,需要调用CreateEventWaitForSingleObject两个函数。

另外,还可以用SetThreadPriority设置线程的优先级,用SuspendThreadResumeThread挂起和恢复线程,用WaitForSingleObjectWaitForMultipleObject实现线程等待,用ExitThreadTerminateThread强制终止线程。

 

在了解了多线程编程以后,就可以继续讲封装了多线程的类的编写了。

首先新建一个空的Win32控制台应用程序,用类向导在其中添加一个名为CMThread的类,类的代码如下:

//MThread.h

#pragma once

 

class CMThread

{

public:

     CMThread(void);

public:

     ~CMThread(void);

 

public:

     voidRun();                 //创建线程

 

private:

     inta;

     intb;

 

private:

     voidThreadA(LPVOIDpParam);              //线程A的线程函数

     voidThreadB(LPVOIDpParam);              //线程B的线程函数

};

 

//MThread.cpp

#include "MThread.h"

#include <iostream>

#include <process.h>

using namespace std;

 

CMThread::CMThread(void)

{

     a= 0;

     b= 1;

}

 

CMThread::~CMThread(void)

{

}

 

void CMThread::ThreadA(LPVOID pParam)

{

     cout<<"线程"<<a<<"调用成功"<<endl;

}

 

void CMThread::ThreadB(LPVOID pParam)

{

     cout<<"线程"<<b<<"调用成功"<<endl;

}

 

//创建线程

void CMThread::Run()

{

     _beginthread(ThreadA, 0, NULL);

     _beginthread(ThreadB, 0, NULL);

}

为了测试多线程类,还需要添加一个main.cpp文件:

//main.cpp

#include "MThread.h"

#include <iostream>

 

void main()

{

     CMThreadmtThread;

     mtThread.Run();

}

 

编译程序,会出现如下错误:

error C3867: 'CMThread::ThreadA':function call missing argument list; use '&CMThread::ThreadA' to create apointer to member

error C3867: 'CMThread::ThreadB':function call missing argument list; use '&CMThread::ThreadB' to create apointer to member

 

双击错误,会发现是_beginthread(ThreadA, 0, NULL)出错,如果只是从字面上理解,似乎是因为函数指针调用方式错误引起的,但是将ThreadA换成&CMThread::ThreadA时仍然不能运行成功。其实这是因为线程函数必须是全局函数。为此需要将线程声明为static函数。这时候又会出现一个新的问题:static类型的函数中不能访问类中其它的非静态成员!解决这个问题的一种方法是将线程函数中用到的类成员函数和变量都声明为static型,但是这种方法显然不实用。另外一种方法是将类本身作为参数传递到线程函数中,为此,需要对线程函数和Run函数作如下修改:

void CMThread::ThreadA(LPVOID pParam)

{

     CMThread*mt = (CMThread*)pParam;

 

     cout<<"线程"<<mt->a<<"调用成功"<<endl;

 

}

 

void CMThread::ThreadB(LPVOID pParam)

{

     CMThread*mt = (CMThread*)pParam;

     cout<<"线程"<<mt->b<<"调用成功"<<endl;

 

}

 

//创建线程

void CMThread::Run()

{

 

     _beginthread(ThreadA, 0, this);

     _beginthread(ThreadB, 0, this);

}

 

这个时候再运行程序就不会报错了,但是多运行几次就会发现,每次运行输出的结果只有一半或是完全没有输出(如下图所示)。原来是线程没有同步。

加上线程同步后的代码如下:

//MThread.h

#pragma once

 

#include <Windows.h>

#include <process.h>

 

class CMThread

{

public:

     CMThread(void);

public:

     ~CMThread(void);

 

public:

     voidRun();                 //创建线程

 

private:

     inta;

     intb;

     HANDLEevThreadAOver;       //用于标识线程A结束的事件

     HANDLEevThreadBOver;       //用于标识线程B结束的事件

 

private:

     staticvoid ThreadA(LPVOID pParam);            //线程A的线程函数

     staticvoid ThreadB(LPVOID pParam);            //线程B的线程函数

};

 

 

//MThread.cpp

#include "MThread.h"

#include <iostream>

using namespace std;

 

CMThread::CMThread(void)

{

     a= 0;

     b= 1;

}

 

CMThread::~CMThread(void)

{

}

 

void CMThread::ThreadA(LPVOID pParam)

{

     CMThread*mt = (CMThread*)pParam;

 

     cout<<"线程"<<mt->a<<"调用成功"<<endl;

 

     SetEvent(mt->evThreadAOver);

}

 

void CMThread::ThreadB(LPVOID pParam)

{

     CMThread*mt = (CMThread*)pParam;

     cout<<"线程"<<mt->b<<"调用成功"<<endl;

 

     SetEvent(mt->evThreadBOver);

}

 

//创建线程

void CMThread::Run()

{

     //产生事件

     evThreadAOver= CreateEvent(NULL,FALSE, FALSE,NULL);

     evThreadBOver= CreateEvent(NULL,FALSE, FALSE,NULL);

 

     //创建线程AB

     _beginthread(ThreadA, 0, this);

     _beginthread(ThreadB, 0, this);

 

     //等待线程AB结束

     WaitForSingleObject(evThreadAOver, INFINITE);

     WaitForSingleObject(evThreadBOver, INFINITE);

}

 

 

//main.cpp

#include "MThread.h"

#include <iostream>

 

void main()

{

     CMThreadmtThread;

     mtThread.Run();

}

 

运行结果如图所示

原创粉丝点击