线程!线程!线程!!!
,特开一贴给同学们讲讲。
主要给出两种常用的线程形式。
1、长等待型线程示例,等待命令,执行不定长的工作,但每个工作的时间不会太长。
2、长工作型线程示例,执行一个很长时间的工作,但可以很快响应取消操作。
主程序
//---------------------------------------
#include "myThreadBUnit.h"
myThreadB *thb=NULL;
//---------------------------------------
void __fastcall TForm1::OnThreadMessage(TMessage& Message)
{
//与线程约定了,显示字串并delete它.
char *p=(char*)Message.LParam;
Memo1->Lines->Add(p);
delete p;
//BEGIN_MESSAGE_MAP
// MESSAGE_HANDLER(WM_USER+100,TMessage,OnThreadMessage);
//END_MESSAGE_MAP(TForm)
}
//---------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//建立线程.
if(thb==NULL)
{
thb=new myThreadB(false);//创建线程并挂起,挂起的目的是向thb写参数.
thb->self=&thb;
thb->mainWin=Handle;
thb->msgMsg=WM_USER+100;
thb->Resume(); //运行线程.
}
}
//---------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
//给线程一个命令.
if(thb!=NULL)
PostThreadMessage(thb->ThreadID,WM_USER+1000,1000,0);
}
//---------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
//结束线程.
if(thb!=NULL)
{
if(!thb->exit())
ShowMessage("线程退出超时!");
}
}
//---------------------------------------
//---------------------------------------
#ifndef myThreadBUnitH
#define myThreadBUnitH
//---------------------------------------
#include <Classes.hpp>
//---------------------------------------
class myThreadB : public TThread
{
private:
void __fastcall runInit();
void __fastcall ShowMess(char *message);
protected:
void __fastcall Execute();
public:
__fastcall myThreadB(bool CreateSuspended);
__fastcall ~myThreadB(void); //析构函数.
HANDLE mainWin; //主线程窗体.
unsigned short int msgMsg; //与主线程通讯用,用于显示线程的消息.
myThreadB **self; //可以把主线程中的线程指针置NULL.
bool __fastcall exit(); //主线程调用,结束线程.
};
//---------------------------------------
#endif
//---------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "myThreadBUnit.h"
#pragma package(smart_init)
//---------------------------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall myThreadB::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------
__fastcall myThreadB::myThreadB(bool CreateSuspended)
: TThread(CreateSuspended)
{
//这里的代码运行在父线程的上下文中.
//无需显示使用delete,就可激活 析构函数.
FreeOnTerminate=true;
self=NULL;
mainWin=NULL;
msgMsg=0;
}
//---------------------------------------
__fastcall myThreadB::~myThreadB(void)
{
char mess[32];
wsprintf(mess,"thread:%d 退出",ThreadID);
ShowMess(mess);
if(self!=NULL)
*self=NULL;
}
//---------------------------------------
void __fastcall myThreadB::runInit()
{
//运行在当前线程环境中.
char mess[32];
wsprintf(mess,"thread:%d 建立",ThreadID);
ShowMess(mess);
}
//---------------------------------------
void __fastcall myThreadB::Execute()
{
MSG msg;
int i=0;
runInit();
//第一种工作形式是长等待,只是偶尔有工作需要做,很快做完又处于等待状态.
//比如标准的视频处理,每帧图像5ms处理完了,需要等35ms,下一帧图像才会来.
ShowMess("长等待");
while(true)//长等待型线程示例,等待命令,执行不定长的工作,但时间不会太长.
{
//检查消息队列,消息队列中无消息则阻塞在此,因此我叫它长等待.
GetMessage(&msg,NULL,0,-1);
if(msg.message==WM_USER+1000) //其它线程发来命令了.
{
Beep(1000,100);//模拟工作100毫秒.
//和主线程通一下讯.
char mess[32];
wsprintf(mess,"thread:%d i:%d",ThreadID,i++);
ShowMess(mess);
}
else if(msg.message==0) //其它线程发来退出消息.
{
if(msg.lParam!=0)
SetEvent((void*)msg.lParam);
break;
}
}
//第二种工作形式,线程是长工作状态.
//长工作又可分为两种形式,
//一种是处于某个冗长的循环中,
//一种是阻塞于某个事件或信号量中.
ShowMess("长工作");
while(true)//长工作型线程示例,执行一个很长时间的工作,但可以很快响应取消操作.
{
//既便是处于长工作状态中,也要想办法至少每秒检查1次消息队列.
//如果线程处于等待某个事件中而没有机会检查消息队列,参考exit()中的注释.
//无论消息队列中有无消息,PeekMessage()都不阻塞线程.
if(PeekMessage(&msg,NULL,0,-1,PM_REMOVE))
{
if(msg.message==0) //主线程发来退出消息.
{
if(msg.lParam!=0)
SetEvent((void*)msg.lParam);
break; //退出线程.
}
}
Beep(1000,1000);//模拟长工作秒.
}
}
//---------------------------------------
bool __fastcall myThreadB::exit()
{
//运行于调用线程的上下文中.
HANDLE exitEvent;
bool exitOK=true;
exitEvent=CreateEvent(NULL,false,false,NULL);
PostThreadMessage(ThreadID,0,0,(long)exitEvent);
//如果线程阻塞于某个事件xxxEvent中,那么需要用SetEvent(xxxEvent)使线程解除阻塞,
//以便线程有机会检查到上面发出的退出消息0.
//如果线程没有快速的检查到退出消息,那么调用线程最多等待(被阻塞)2000ms.
if(WAIT_TIMEOUT==WaitForSingleObject(exitEvent,2000))
exitOK=false;
CloseHandle(exitEvent);
return exitOK;
}
//---------------------------------------
void __fastcall myThreadB::ShowMess(char *message)
{
if(mainWin==NULL)
return;
char *newStr=new char[128];
lstrcpyn(newStr,message,128);
PostMessage(mainWin,msgMsg,0,(long)newStr);
//不要在此delete newStr.
//和主线程约定,newStr在主线程中delete.
}
//---------------------------------------