如何让程序自动管理线程
如何让程序自动管理线程
程序员之家 作者:不详 日期:2003-1-29 16:16:00
--------------------------------------------------------------------------------
引言
多线程是一种很好的程序机制,使用线程可以充分的利用电脑资源,进行并行的业务处理。不过好的东西总有它的不足。线程是好,不过滥用,或管理不当就会造成线程混乱,内存漏洞,造成电脑速度变慢,反应迟钝。
想法
于是有人提出能不能让线程自己管理自己,把这复杂的工作交给电脑来处理。笔者经过多年的实践,终于用VC++实现了这一目的。
大家知道在VC++中我们可以用CreateThread创建一个线程,该函数返回这线程的Handle,以后我们就可以用这个Handle来管理这个线程的。于是我们可以做一个类名为ThreadManager,来管理这些Handle,并随时监控这些线程的状态。
总的思想就是这样,不过为了方便使用,我们最好把这个类封装成DLL的形式,这样以后我们在任何程序中都可以很方便的用该类来管理线程了(当然如果你有兴趣,也可以用COM模型来实现)。
实现
因为我们要把一切工作全交给ThreadManager,所以线程的创建,监控,删除都将在该类中实现,而我们仅要做的就是把线程函数名和线程参数传给ThreadManager类,于是我们定义该类构造函数为:ThreadManager(ThreadPrc threadpro,LPVOID pParam);
该类还要能启动线程,于是我们又定义一个启动函数:
RunThread();
另外我们有时还要能获得线程的Handle,于是又定义一个函数:
HANDLE GetThreadHandle();
而该类唯一的成员参数就是Handle:
HANDLE m_Handle;
于是ThreadManager定义如下:
typedef DWORD (WINAPI *ThreadPro)(LPVOID);
class CThreadManager : public CObject
{
DECLARE_DYNAMIC( CThreadManager )
public:
CThreadManager( ThreadPrc threadpro, LPVOID pParam);
~CThreadManager();
CBOOL RunThread();
HANDLE GetThreadHandle() const { return( m_Handle ); };
private:
HANDLE m_Handle;
};
显然,我们仅有这一个类还不能完成我们所需的工作,我们还要一个负责具体监控的ThreadTask类,ThreadTask类中有一个监控线程ThreadTaskFunc( )负责监控并删除线程。该类定义如下:
class CThreadTask : public CObject
{
DECLARE_DYNAMIC( CThreadTask )
public:
CThreadTask(); 构造函数
~CThreadTask();
CBOOL IsValid();
void AddHandle( CONST HANDLE cHandle ); 添加线程句柄到m_ObList中
void CloseThreadHandles(); (关闭线程)
static CThreadTask& GetCThreadTask(); 用于在Managerthread类中获得ThreadTask类的指针
CObList m_ObList;线程句柄组
HANDLE m_Handle;线程句柄
BOOL m_bKeepGoing;是否已运行
};
IMPLEMENT_DYNAMIC( CThreadCareTaker, CObject )
其中IsValid()是用于检验ThreadTaskFunc()是否已动行了,其它意思都很明显。
流程图
总的流程图如下:
具体实现
下面给出它的具体实现。
ThreadTask::ThreadTask()
{
m_bKeepGoing = TRUE;
表示已运行
DWORD nThreadId = 0;
m_Handle = (HANDLE)::CreateThread(NULL,0,ThreadTaskpro,0,0,&nThreadId );
创建管理线程
}
void ThreadTask::AddHandle( CONST HANDLE cHandle )
{
CHandle *pHandle = new CHandle;
pHandle->m_ThreadHandle = cHandle;
m_ObList.AddTail( pHandle );
}
void ThreadTask::CloseThreadHandles()
{
if ( m_ObList.GetCount() )
{
POSITION pos1, pos2;
CHandle *pHandle = (CHandle *)NULL;
(CHandle类相当简单,只有一个成员函数m_ThreadHandle)
DWORD dwExitCode = 0L;
for( pos1=m_ObList.GetHeadPosition(); (pos2=pos1)!=POSITION(NULL); )
{
历遍所有已有的线程句柄
pHandle = DYNAMIC_DOWNCAST( CHandle, m_ObList.GetNext( pos1 ) );
获得第pos1个handle
VERIFY( ::GetExitCodeThread( pHandle->m_ThreadHandle, &dwExitCode ) );
获得线程pHandle的当前状态
if ( dwExitCode != STILL_ACTIVE )
如果已完成
{
释放当前句柄
m_ObList.RemoveAt( pos2 );
VERIFY( ::CloseHandle( pHandle->m_ThreadHandle ) );
delete pHandle;
pHandle = (CHandle *)NULL;
}
}
}
}
ThreadTask::~ThreadTask()
{
}
ThreadTask & ThreadTask::GetThreadTask()
{
返回静态ThreadTask对象,以便ThreadManager类调用
static ThreadTask Taker;
return (Taker) ;
}
BOOL ThreadTask::IsValid()
{
是否已运行
BOOL bValid_Status = FALSE;
if ( (this != NULL)
&& AfxIsValidAddress( this, sizeof( ThreadTask ) )
)
bValid_Status = TRUE;
return( bValid_Status );
}
下面介绍线程ThreadTaskpro();
该线程最主要的目的就是调用ThreadTask的CloseThreadHandles()函数,实现如下:
DWORD WINAPI ThreadTaskpro( LPVOID pParam )
{
HANDLE hCurrentThread = GetCurrentThread();
获得该线程句柄
SetThreadPriority( hCurrentThread, THREAD_PRIORITY_LOWEST );
设为最低
while ( ThreadTask::GetThreadTask().m_bKeepGoing )
{
Sleep(500);
休息500mms
ThreadTask::GetThreadTask().CloseThreadHandles();
}
SetThreadPriority( hCurrentThread, THREAD_PRIORITY_NORMAL );
return( 0 );
}
ThreadTask类到这就介绍完了,下面我们看看ThreadManager类的实现,其实它的工作已很小,就是启动要管理的线程(在构造函数中完成),并控制ThreadTask类。
具体实现:
ThreadManager::ThreadManager(ThreadPro threadpro, LPVOID pParam)
{
DWORD nThreadId = 0;
_ASSERTE( ThreadTask::GetThreadTask().IsValid() );
运行ThreadTask类
m_Handle = (HANDLE)::CreateThread(NULL,0,threadpro,(LPVOID)pParam,0,&nThreadId );
创建要管理的线程,并返回句柄
if ( ThreadTask::GetThreadTask().m_bKeepGoing )
{
如果ThreadTask运行了的话
ASSERT( m_Handle );
ThreadTask::GetThreadTask().AddHandle( m_Handle );
把句柄加入ThreadTask类中,以便管理
}
}
ThreadManager::~ThreadManager()
{
}
BOOL ThreadManager::RunThread()
{
运行线程
return( ::ResumeThread( m_Handle ) != 0xFFFFFFFF );
}
整在机制就介绍完了。
使用方法
使用方法相当简单,比如说,我要运行进程MyThread1,并传入参数m_pro,只要用以下代码就可以了:
ThreadManager ThreadManager( &MyThread1, (LPVOID)m_pro );
ThreadManager.RunThread();
就可以了,用这种方法创的线程,会自动由ThreadManager类管理,并在完成的工作时,自动释放线程资源。
赵明
email: papaya_zm@sina.com;zmpapaya@hotmail.com
web: http://h2osky.126.com
如何让程序自动管理线程
程序员之家 作者:不详 日期:2003-1-29 16:16:00
--------------------------------------------------------------------------------
引言
多线程是一种很好的程序机制,使用线程可以充分的利用电脑资源,进行并行的业务处理。不过好的东西总有它的不足。线程是好,不过滥用,或管理不当就会造成线程混乱,内存漏洞,造成电脑速度变慢,反应迟钝。
想法
于是有人提出能不能让线程自己管理自己,把这复杂的工作交给电脑来处理。笔者经过多年的实践,终于用VC++实现了这一目的。
大家知道在VC++中我们可以用CreateThread创建一个线程,该函数返回这线程的Handle,以后我们就可以用这个Handle来管理这个线程的。于是我们可以做一个类名为ThreadManager,来管理这些Handle,并随时监控这些线程的状态。
总的思想就是这样,不过为了方便使用,我们最好把这个类封装成DLL的形式,这样以后我们在任何程序中都可以很方便的用该类来管理线程了(当然如果你有兴趣,也可以用COM模型来实现)。
实现
因为我们要把一切工作全交给ThreadManager,所以线程的创建,监控,删除都将在该类中实现,而我们仅要做的就是把线程函数名和线程参数传给ThreadManager类,于是我们定义该类构造函数为:ThreadManager(ThreadPrc threadpro,LPVOID pParam);
该类还要能启动线程,于是我们又定义一个启动函数:
RunThread();
另外我们有时还要能获得线程的Handle,于是又定义一个函数:
HANDLE GetThreadHandle();
而该类唯一的成员参数就是Handle:
HANDLE m_Handle;
于是ThreadManager定义如下:
typedef DWORD (WINAPI *ThreadPro)(LPVOID);
class CThreadManager : public CObject
{
DECLARE_DYNAMIC( CThreadManager )
public:
CThreadManager( ThreadPrc threadpro, LPVOID pParam);
~CThreadManager();
CBOOL RunThread();
HANDLE GetThreadHandle() const { return( m_Handle ); };
private:
HANDLE m_Handle;
};
显然,我们仅有这一个类还不能完成我们所需的工作,我们还要一个负责具体监控的ThreadTask类,ThreadTask类中有一个监控线程ThreadTaskFunc( )负责监控并删除线程。该类定义如下:
class CThreadTask : public CObject
{
DECLARE_DYNAMIC( CThreadTask )
public:
CThreadTask(); 构造函数
~CThreadTask();
CBOOL IsValid();
void AddHandle( CONST HANDLE cHandle ); 添加线程句柄到m_ObList中
void CloseThreadHandles(); (关闭线程)
static CThreadTask& GetCThreadTask(); 用于在Managerthread类中获得ThreadTask类的指针
CObList m_ObList;线程句柄组
HANDLE m_Handle;线程句柄
BOOL m_bKeepGoing;是否已运行
};
IMPLEMENT_DYNAMIC( CThreadCareTaker, CObject )
其中IsValid()是用于检验ThreadTaskFunc()是否已动行了,其它意思都很明显。
流程图
总的流程图如下:
具体实现
下面给出它的具体实现。
ThreadTask::ThreadTask()
{
m_bKeepGoing = TRUE;
表示已运行
DWORD nThreadId = 0;
m_Handle = (HANDLE)::CreateThread(NULL,0,ThreadTaskpro,0,0,&nThreadId );
创建管理线程
}
void ThreadTask::AddHandle( CONST HANDLE cHandle )
{
CHandle *pHandle = new CHandle;
pHandle->m_ThreadHandle = cHandle;
m_ObList.AddTail( pHandle );
}
void ThreadTask::CloseThreadHandles()
{
if ( m_ObList.GetCount() )
{
POSITION pos1, pos2;
CHandle *pHandle = (CHandle *)NULL;
(CHandle类相当简单,只有一个成员函数m_ThreadHandle)
DWORD dwExitCode = 0L;
for( pos1=m_ObList.GetHeadPosition(); (pos2=pos1)!=POSITION(NULL); )
{
历遍所有已有的线程句柄
pHandle = DYNAMIC_DOWNCAST( CHandle, m_ObList.GetNext( pos1 ) );
获得第pos1个handle
VERIFY( ::GetExitCodeThread( pHandle->m_ThreadHandle, &dwExitCode ) );
获得线程pHandle的当前状态
if ( dwExitCode != STILL_ACTIVE )
如果已完成
{
释放当前句柄
m_ObList.RemoveAt( pos2 );
VERIFY( ::CloseHandle( pHandle->m_ThreadHandle ) );
delete pHandle;
pHandle = (CHandle *)NULL;
}
}
}
}
ThreadTask::~ThreadTask()
{
}
ThreadTask & ThreadTask::GetThreadTask()
{
返回静态ThreadTask对象,以便ThreadManager类调用
static ThreadTask Taker;
return (Taker) ;
}
BOOL ThreadTask::IsValid()
{
是否已运行
BOOL bValid_Status = FALSE;
if ( (this != NULL)
&& AfxIsValidAddress( this, sizeof( ThreadTask ) )
)
bValid_Status = TRUE;
return( bValid_Status );
}
下面介绍线程ThreadTaskpro();
该线程最主要的目的就是调用ThreadTask的CloseThreadHandles()函数,实现如下:
DWORD WINAPI ThreadTaskpro( LPVOID pParam )
{
HANDLE hCurrentThread = GetCurrentThread();
获得该线程句柄
SetThreadPriority( hCurrentThread, THREAD_PRIORITY_LOWEST );
设为最低
while ( ThreadTask::GetThreadTask().m_bKeepGoing )
{
Sleep(500);
休息500mms
ThreadTask::GetThreadTask().CloseThreadHandles();
}
SetThreadPriority( hCurrentThread, THREAD_PRIORITY_NORMAL );
return( 0 );
}
ThreadTask类到这就介绍完了,下面我们看看ThreadManager类的实现,其实它的工作已很小,就是启动要管理的线程(在构造函数中完成),并控制ThreadTask类。
具体实现:
ThreadManager::ThreadManager(ThreadPro threadpro, LPVOID pParam)
{
DWORD nThreadId = 0;
_ASSERTE( ThreadTask::GetThreadTask().IsValid() );
运行ThreadTask类
m_Handle = (HANDLE)::CreateThread(NULL,0,threadpro,(LPVOID)pParam,0,&nThreadId );
创建要管理的线程,并返回句柄
if ( ThreadTask::GetThreadTask().m_bKeepGoing )
{
如果ThreadTask运行了的话
ASSERT( m_Handle );
ThreadTask::GetThreadTask().AddHandle( m_Handle );
把句柄加入ThreadTask类中,以便管理
}
}
ThreadManager::~ThreadManager()
{
}
BOOL ThreadManager::RunThread()
{
运行线程
return( ::ResumeThread( m_Handle ) != 0xFFFFFFFF );
}
整在机制就介绍完了。
使用方法
使用方法相当简单,比如说,我要运行进程MyThread1,并传入参数m_pro,只要用以下代码就可以了:
ThreadManager ThreadManager( &MyThread1, (LPVOID)m_pro );
ThreadManager.RunThread();
就可以了,用这种方法创的线程,会自动由ThreadManager类管理,并在完成的工作时,自动释放线程资源。