从Win32 API封装Thread类[1]

转载 2007年10月15日 23:18:00

前几天在学Windows多线程程序设计,发现Win32 API用起来确实不怎么方便,特别是对于C++程序员。于是实现了一个简单的封装,技术含量当然不高,不过用起来还是比较方便的。如果你熟悉Java,你会发现这个实现有点像Java的Thread,在Java中有两种方法可以创建一个Thread:

1.从Thread类继承并实现run方法:

1 class MyThread extends  Thread {
2     public void
 run() {
3 
        ...
4 
    } 
5 
};
6 

7 //开启线程
8 MyThread thread = new  MyThread;
9 thread.start();

2.声明一个类实现Runnable接口并实现run方法:

1 class MyRunnable implements  Runnable {
2     public void
 run() {
3 
        ...
4 
    }
5 
};
6 

7 // 开启线程 
8 MyThread thread = new MyThread(new  MyRunnable);
9 thread.start();


具体实现
Java的实现方式还算优雅,我们也可以在C++中模拟,由于篇幅所限,在这里我们只关注基本功能的实现:
thread.h
 1 #ifndef THREAD_H
 2 
#define THREAD_H
 3 

 4 #include <windows.h>
 5 
 6 #define CLASS_UNCOPYABLE(classname) /
 7     private
: /
 8     classname##(const classname##&
); /
 9     classname##& operator=(const classname##&
);
10 

11 struct Runnable {
12     virtual void run() = 0
;
13     virtual ~
Runnable() {}
14 
};
15 

16 class Thread : public Runnable {
17 
    CLASS_UNCOPYABLE(Thread)
18 public
:
19     explicit Thread(Runnable *target = 0
);
20     virtual ~
Thread();
21     virtual void
 run() {}
22     void
 start();
23     void
 join();
24 private
:
25     static unsigned __stdcall threadProc(void *
param);
26 private
:
27     Runnable *
_target;
28 
    HANDLE _handle;
29 
};
30 

31 #endif/*THREAD_H*/

在上面的代码中我们先定义一个Runnable类,并为Runnable类添加纯虚函数run,需要特别注意的是Runnable类的虚析构函数,任何想要成为基类的class都应该声明析构函数为virtual。
Thread类直接继承自Runnable,CLASS_UNCOPYABLE(Thread) 这一行用宏声明Thread类不可拷贝,具体细节请看 考虑用Macro替换Uncopyable 。start成员函数和Java中的一样,用来开启一个线程,join成员函数用来阻塞当前线程直到开启的线程执行完毕。threadProc作为静态成员函数用来传递给_beginthreadex,至于为什么用_beginthreadex代替CreateThread请问Google。初步的实现都比较简单,直接贴上代码:
thread.cpp
 1 #include "thread.h"
 2 #include <process.h> //for _beginthreadex
 3 
 4 Thread::Thread(Runnable *target /*= 0*/)
 5 :_target(target
)
 6 ,_handle(0
) {
 7 

 8 }
 9 

10 Thread::~Thread() {
11     if (_handle != 0
)
12 
        CloseHandle(_handle);
13     if (_target != 0
)
14 
        delete _target;
15 
}
16 

17 void Thread::start() {
18     if (_handle != 0
)
19         return
;
20 
    unsigned id;
21     _handle = reinterpret_cast<HANDLE>
(
22         _beginthreadex(00, threadProc, this0&
id)
23 
        );
24 
}
25 

26 void Thread::join() {
27     if(_handle != 0
) {
28 
        WaitForSingleObject(_handle, INFINITE);
29 
        CloseHandle(_handle);
30         _handle = 0
;
31 
    }
32 
}
33 

34 unsigned __stdcall Thread::threadProc(void *param) {
35     Thread *= static_cast<Thread*>
(param);
36     if (p->_target != 0
)
37         p->_target->
run();
38     else

39         p->run();
40     return 0
;
41 }

下面是测试代码:
test.cpp
 1 #include "thread.h"
 2 #include <iostream>
 3 
 4 using namespace std;
 5 

 6 //第一种方法,从Thread类继承
 7 struct MyThread : public Thread {
 8     virtual void
 run() {
 9         for (int i = 0; i < 5++
i) {
10             cout << "MyThread Running..." << i <<
 endl;
11             Sleep(100
);
12 
        }
13 
    }
14 
};
15 

16 //第二种方法,“实现”Runnable接口
17 struct MyRunnable : public Runnable {
18     virtual void
 run() {
19         for (int i = 0; i < 5++
i) {
20             cout << "MyRunnable Running..." << i <<
 endl;
21             Sleep(300
);
22 
        }
23 
    }
24 
};
25 

26 int main() {
27 

28     MyThread thread1;
29     Thread thread2(new
 MyRunnable());
30 
    thread1.start();
31 
    thread2.start();
32 
    thread1.join();
33 
    thread2.join();
34 

35     return 0;
36 }

可能的运行结果:
MyThread Running...0
MyRunnable Running...0
MyThread Running...1
MyThread Running...2
MyRunnable Running...1
MyThread Running...3
MyThread Running...4
MyRunnable Running...2
MyRunnable Running...3
MyRunnable Running...4


如果你熟悉boost库,你会知道boost库的Thread构造函数可以接受普通函数和函数对象作为参数,如果你觉得从Thread类继承或者实现Runnable接口还不够简洁,下一篇会有一个比较好的改进。

posted  by  蚂蚁终结者

俄罗斯方块教程(win32,C语言)

关于内容 本系列视频共43小节,每小节平均15分钟。 代码主要基于C语言,少量win32编程。即使大家不会win32也完全不要紧,课程涉及到的win32,全部精讲,大家一定会有很大的收获。
  • 2017年04月14日 17:03

win32 thread封装cthread

  • 2010年02月01日 17:27
  • 8KB
  • 下载

Win32多线程之CreateThread

1.CreateThread    产生一个线程(并因而成就一个多线程程序),是以CreateThread()作为一切行动的开始,次函数的原型如下: HANDLE CreateThread(  LPS...
  • wjj715211
  • wjj715211
  • 2013-11-16 01:37:36
  • 2566

Windows和Linux上分别怎样实现等待某个线程结束?---用WaitForSingleObject和pthread_join

Windows和Linux上分别怎样实现等待某个线程结束呢, 我们先看Windows的情形, 直接上代码: #include #include DWORD WINAPI Fun1Proc(LPV...
  • stpeace
  • stpeace
  • 2015-01-29 23:26:27
  • 5681

关于Windows Thread

昨天在看老工程中的代码的时候,发现其中创建了一个线程后,并没有通过CloseHandle函数来关闭该句柄。抱着怀疑的态度,就查了些相关的资料,现把自己的调查结果总结如下。1、创建线程可以通过调用Cre...
  • njuitjf
  • njuitjf
  • 2010-02-21 16:55:00
  • 2959

采用CreateThread()创建多线程程序

采用CreateThread()创建多线程程序 在window环境下,Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作: 1、主要的函数列表: ...
  • cbNotes
  • cbNotes
  • 2012-12-10 11:44:59
  • 37327

Windows多线程总结(1)-- 线程的创建

创建线程我们需要使用CreateThread函数来完成, HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD SIZ...
  • oBuYiSeng
  • oBuYiSeng
  • 2015-11-27 16:17:59
  • 2062

windows多线程详解

在一个牛人的博客上看到了这篇文章,所以就转过来了,地址是http://blog.csdn.net/morewindows/article/details/7421759 本文将带领你与多线程作第一次...
  • zhouxuguang236
  • zhouxuguang236
  • 2012-07-23 14:26:35
  • 52801

windows thread的简单使用

由于主要使用pthread-win32,所以对windows自带的线程没那么熟练,写个例子练下手:#include #include #include #include #includ...
  • jaff20071234
  • jaff20071234
  • 2011-03-31 17:46:00
  • 4900

Win32Thread

Win32Thread是指向_W32THREAD结构体的指针,通过这个结构体可以获得钩子所在进程ID和线程ID.该结构体定义如下。   typedef struct _W32THREAD { PVO...
  • wetgsg
  • wetgsg
  • 2014-08-08 09:35:24
  • 614
收藏助手
不良信息举报
您举报文章:从Win32 API封装Thread类[1]
举报原因:
原因补充:

(最多只允许输入30个字)