用VC++创建一个新线程
2007/2/13 12:57
用VC++创建一个新线程本程序将使用到的函数原型如下:
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
上面的两个函数我们常使用第一个。
其中(1)pfnThreadProc表示要做为一个新线程启动的那个函数(必须事先定义一个全局函数),并且该函数必须是如下格式:
UINT MyControllingFunction( LPVOID pParam )
{
//这里可以添加一个cpu占用率很高的程序,也可以是一个死循环程序。
//如果是有窗体的任务列表中会出现该线程名称,即窗体名称。
return 0;
}
(2)pParam就表示为新线程指定的窗口句柄,如: AfxGetMainWnd()->m_hWnd
(3)nPriority表示这个线程的优先级,可选的常有:
THREAD_PRIORITY_ABOVE_NORMAL 比正常的优先级高一点;
THREAD_PRIORITY_BELOW_NORMAL 比正常的优先级低一点;
THREAD_PRIORITY_HIGHEST 比正常的优先级高两点;
THREAD_PRIORITY_IDLE 设置优先级基数为1;
THREAD_PRIORITY_LOWEST 比正常的优先级低两点;
THREAD_PRIORITY_TIME_CRITICAL 设置优先级基数为15;
0 设置优先级为正常。 后面还有很多参数可以都是0,也可以省略。
★本实例将创建一个线程,其原代码如下:
UINT Proc1(LPVOID param)//按第一个参数要求格式创建一个函数。
{
int i;
for(i=0;i=1000;i++)//因为i=1000,所以本程序将死循环。
{
::MessageBeep(0);
}
return 0;
}
void CMy111Dlg::OnCancel()//在另一个按钮中创建该函数的新线程。
{
HWND hWnd=GetSafeHwnd();//取得当前窗口的句柄供函数使用。
AfxBeginThread(Proc1,hWnd,0);//以正常优先级调用。
//Proc1(AfxGetMainWnd()->m_hWnd);
}
从上例可以看出,用这种方法运行该死程序,主窗口还可以被托动,但如果把上例改为
Proc1(AfxGetMainWnd()->m_hWnd) // 虽然程序可以运行,但主窗口无法被移动。
此代码归7CTT所有,代码均调试通过。
CreateEvent
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
BOOL bManualReset, // reset type
BOOL bInitialState, // initial state
LPCTSTR lpName // object name
);
该函数创建一个Event同步对象,并返回该对象的Handle
lpEventAttributes 一般为NULL
bManualReset 创建的Event是自动复位还是人工复位 ,如果true,人工复位,
一旦该Event被设置为有信号,则它一直会等到ResetEvent()API被调用时才会恢复
为无信号. 如果为false,Event被设置为有信号,则当有一个wait到它的Thread时,
该Event就会自动复位,变成无信号.
bInitialState 初始状态,true,有信号,false无信号
lpName Event对象名
一个Event被创建以后,可以用OpenEvent()API来获得它的Handle,用CloseHandle()
来关闭它,用SetEvent()或PulseEvent()来设置它使其有信号,用ResetEvent()
来使其无信号,用WaitForSingleObject()或WaitForMultipleObjects()来等待
其变为有信号.
PulseEvent()是一个比较有意思的使用方法,正如这个API的名字,它使一个Event
对象的状态发生一次脉冲变化,从无信号变成有信号再变成无信号,而整个操作是原子的.
对自动复位的Event对象,它仅释放第一个等到该事件的thread(如果有),而对于
人工复位的Event对象,它释放所有等待的thread.
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, pointer to security attributes
DWORD dwStackSize, initial thread stack size
LPTHREAD_START_ROUTINE lpStartAddress, pointer to thread function
LPVOID lpParameter, argument for new thread
DWORD dwCreationFlags, creation flags
LPDWORD lpThreadId pointer to receive thread ID
);
第一个参数是指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL。第二个参数是用于新线程的初始堆栈大小,默认值为0。在任何情况下,Windows根据需要动态延长堆栈的大小。
CreateThread的第三个参数是指向线程函数的指标。函数名称没有限制,但是必须以下列形式声明:
DWORD WINAPI ThreadProc (PVOID pParam) ;
CreateThread的第四个参数为传递给ThreadProc的参数。这样主线程和从属线程就可以共享数据。
CreateThread的第五个参数通常为0,但当建立的线程不马上执行时为旗标CREATE_SUSPENDED。线程将暂停直到呼叫ResumeThread来恢复线程的执行为止。第六个参数是一个指标,指向接受执行绪ID值的变量。
我的应用:
HANDLE hThread = CreateThread(NULL, 0, InitKyuyoUIGlobalKankyo, 0, 0, &dwThreadID);
DWORD WINAPI InitKyuyoUIGlobalKankyo(LPVOID lpParameter)
{
CoInitialize(NULL);
temparay location of the function below.
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT(GlobleInitialize));
if(NULL == hEvent){
return 0;
}
WaitForSingleObject(hEvent, INFINITE);
long userId = 0;
KyuyoUIGlobalGetKankyoSettei(userId);
CloseHandle(hEvent);
CoUninitialize();
return 0;
}
c++ 字符类型总结
1.区别wchar_t,char,WCHAR ANSI:即 char,可用字符串处理函数:strcat( ),strcpy( ), strlen( )等以str打头的函数。 UNICODE:wchar_t是Unicode字符的数据类型,它实际定义在里: typedef unsigned short wchar_t; 另外,在头文件中有这样的定义:typedef wchar_t WCHAR; 所以WCHAR实际就是wchar_t wchar_t 可用字符串处理函数:wcscat(),wcscpy(),wcslen()等以wcs打头的函数。为了让编译器识别Unicode字符串,必须以在前面加一个“L”,例如: wchar_t *szTest=L"This is a Unicode string."; 2.TCHAR 在C语言里面提供了 _UNICODE宏(有下划线),在Windows里面提供了UNICODE宏(无下划线),只要定了_UNICODE宏和UNICODE宏,系统就会自 动切换到UNICODE版本,否则,系统按照ANSI的方式进行编译和运行。只定义了宏并不能实现自动的转换,他还需要一系列的字符定义支持。 1. TCHAR 如果定义了UNICODE宏则TCHAR被定义为wchar_t。 typedef wchar_t TCHAR; 否则TCHAR被定义为char typedef char TCHAR; 2. LPTSTR 如果定义了UNICODE宏则LPTSTR被定义为LPWSTR。 typedef LPTSTR LPWSTR; 否则TCHAR被定义为char typedef LPTSTR LPSTR; 说明:在使用字符串常量的时候需要使用_TEXT(“MyStr”)或者_T("")来支持系统的自动转换。 3.BSTR BSTR是一个带长度前缀的字符串,主要由操作系统来管理的,所以要用api.主要用来和VB打交道的(VB里的string就是指它)要操作它的API函数有很多.比如SysAllocString,SysFreeString等等. vc里封装它的类如_bstr_t,及ATL中的CComBSTR等. 一个 BSTR 由头部和字符串组成,头部包含了字符串的长度信息,字符串中可以包含嵌入的 null 值。 BSTR 是以指针的形式进行传递的。(指针是一个变量,包含另外一个变量的内存地址,而不是数据。) BSTR 是 Unicode 的,即每个字符需要两个字节。 BSTR 通常以两字节的 null 字符结束。 wstr是宽字符,以双字节表示一个字符 bstr是为了与原先的basic字符兼容,它的最前面的4个字节为其长度,以'/0'结束. 4.更进一步的字符串以及其指针的类型定义 由于Win32 API文档的函数列表使用函数的常用名字(例如, "SetWindowText"),所有的字符串都是用TCHAR来定义的。(除了XP中引入的只适用于Unicode的API)。下面列出一些常用的typedefs,你可以在msdn中看到他们。 type Meaning in MBCS builds Meaning in Unicode builds
WCHAR wchar_t wchar_t
LPSTR char* char*
LPCSTR const char* const char*
LPWSTR wchar_t* wchar_t*
LPCWSTR wchar_t* wchar_t*
TCHAR TCHAR char wchar_t
LPTSTR TCHAR* TCHAR*
LPCTSTR const TCHAR* const TCHAR*
5.相互转换 (1) char*转换成CString 若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:char chArray[] = "This is a test";
char * p = "This is a test"; 或LPSTR p = "This is a test"; 或在已定义Unicode应的用程序中TCHAR * p = _T("This is a test"); 或LPTSTR p = _T("This is a test");
CString theString = chArray;
theString.Format(_T("%s"), chArray);
theString = p; (2) CString转换成char* 若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法: 方法一,使用强制转换。例如:CString theString( "This is a test" );
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString; 方法二,使用strcpy。例如:CString theString( "This is a test" );
LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
_tcscpy(lpsz, theString); 需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。 方法三,使用CString::GetBuffer。例如:CString s(_T("This is a test "));
LPTSTR p = s.GetBuffer();
// 在这里添加使用p的代码
if(p != NULL) *p = _T('/0');
s.ReleaseBuffer();
// 使用完后及时释放,以便能使用其它的CString成员函数 (3) BSTR转换成char* 方法一,使用ConvertBSTRToString。例如:#include
#pragma comment(lib, "comsupp.lib")
int _tmain(int argc, _TCHAR* argv[]){
BSTR bstrText = ::SysAllocString(L"Test");
char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
SysFreeString(bstrText); // 用完释放
delete[] lpszText2;
return 0;
} 方法二,使用_bstr_t的赋值运算符重载。例如:_bstr_t b = bstrText;
char* lpszText2 = b; (4) char*转换成BSTR 方法一,使用SysAllocString等API函数。例如:BSTR bstrText = ::SysAllocString(L"Test");
BSTR bstrText = ::SysAllocStringLen(L"Test",4);
BSTR bstrText = ::SysAllocStringByteLen("Test",4); 方法二,使用COleVariant或_variant_t。例如://COleVariant strVar("This is a test");
_variant_t strVar("This is a test");
BSTR bstrText = strVar.bstrVal; 方法三,使用_bstr_t,这是一种最简单的方法。例如:BSTR bstrText = _bstr_t("This is a test"); 方法四,使用CComBSTR。例如:BSTR bstrText = CComBSTR("This is a test"); 或CComBSTR bstr("This is a test");
BSTR bstrText = bstr.m_str; 方法五,使用ConvertStringToBSTR。例如:char* lpszText = "Test";
BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText); (5) CString转换成BSTR 通常是通过使用CStringT::AllocSysString来实现。例如:CString str("This is a test");
BSTR bstrText = str.AllocSysString();
…
SysFreeString(bstrText); // 用完释放 (6) BSTR转换成CString 一般可按下列方法进行:BSTR bstrText = ::SysAllocString(L"Test");
CStringA str;
str.Empty();
str = bstrText; 或CStringA str(bstrText); (7) ANSI、Unicode和宽字符之间的转换 方法一,使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。 方法二,使用“_T”将ANSI转换成“一般”类型字符串,使用“L”将ANSI转换成Unicode,而在托管C++环境中还可使用S将ANSI字符串转换成String*对象。例如:TCHAR tstr[] = _T("this is a test");
wchar_t wszStr[] = L"This is a test";
String* str = S”This is a test”; 方法三,使用ATL 7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类,它具有如图3所示的统一形式: 其中,第一个C表示“类”,以便于ATL 3.0宏相区别,第二个C表示常量,2表示“to”,EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、 T、W和OLE,其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如,CA2CT就是将ANSI转换成一般类型的字符串常量。下面 是一些示例代码:LPTSTR tstr= CA2TEX<16>("this is a test");
LPCTSTR tcstr= CA2CT("this is a test");
wchar_t wszStr[] = L"This is a test";
char* chstr = CW2A(wszStr);
常用的类:
CRect用来表示矩形的类,拥有四个成员变量:top left bottom right。分别表是左上角和右下角的坐标。可以通过以下的方法构造:
CRect( int l, int t, int r, int b ); 指明四个坐标
CRect( const RECT& srcRect ); 由RECT结构构造
CRect( LPCRECT lpSrcRect ); 由RECT结构构造
CRect( POINT point, SIZE size ); 有左上角坐标和尺寸构造
CRect( POINT topLeft, POINT bottomRight ); 有两点坐标构造
下面介绍几个成员函数:
int Width( ) const; 得到宽度
int Height( ) const; 得到高度
CSize Size( ) const; 得到尺寸
CPoint& TopLeft( ); 得到左上角坐标
CPoint& BottomRight( ); 得到右下角坐标
CPoint CenterPoint( ) const; 得当中心坐标
此外矩形可以和点(CPoint)相加进行位移,和另一个矩形相加得到“并”操作后的矩形。
1. CArray()
CArray类为模板类,基类为CObject类,定义如下:
Template<class TYPE,class ARG_TYPE> class CArray:public CObject
CArray类的对象的操作类似于C语言中的数组,而且CArray类对象的大小可以根据需要动态地缩小或增加。其类成员如下:
CArray:构造一个空的数组,每次可以往数组中添加一个元素。
RemoveAll:删除数组中的所有的元素。
GetAt:返回指定索引的数组元素。
SetAt:设置指定索引处的数组元素。
Add:在数组的尾部添加一个元素。
RemoveAt:删除指定索引处的一个或多个数组元素。
InsertAt:在指定的索引处插入数组元素。
CPoint:用来表示一个点的坐标,有两个成员变量:x y。 可以和另一个点相加。
CString:用来表示可变长度的字符串。使用CString可不指明内存大小,CString会根据需要自行分配。下面介绍几个成员函数:
GetLength 得到字符串长度
GetAt 得到指定位置处的字符
operator + 相当于strcat
void Format( LPCTSTR lpszFormat, ... ); 相当于sprintf
Find 查找指定字符,字符串
Compare 比较
CompareNoCase 不区分大小写比较
MakeUpper 改为小写
MakeLower 改为大写
GetLength:返回字符串数组中字符的个数,以字节为单位,不包括字符串结束符。
IsEmpty:测试一个字符串类对象中的内容是否为空。
Empty:清空字符串对象中的内容,可以释放内存。
GetAt:返回字符串中指定索引序号的字符。
SetAt:设置字符串中指定索引位置的字符,与GetAt函数功能一致。
Compare:实现对两个字符串进行比较,区分大小写。
Mid:将字符串以nFirst为起始点抽取一个子字符串。
Left:抽取字符串左边的个数为nCount的子字符串。
Right:抽取字符串右边的个数为nCount的子字符串。
Remove:将字符串中指定的字符删除。
Insert:在字符串中指定的索引位置插入一个或多个字符。
Delete:在字符串中指定索引位置删除一个或多个字符。
5.CTime
在应用程序中可以有CTime类来处理时间。其成员函数如下:
GetCurrentTime:获取当前系统时间,并构造一个CTime类的对象作为返回值。
GetTime:返回一个time_t类型的相应的时间值。
GetYear:返回CTime对象中年的数值,时间范围从1970年1月1日到2038年1月18日
GetMonth:返回CTime对象中的月的数,范围从1到12。
GetDay:返回CTime对象中天的数值,数值范围从1到31。
GetHour:返回CTime对象中的小时的数值,范围从1到23。
GetMinute:返回CTime对象中的分钟的数值,数值范围从1到59。
GetSecond:返回CTime对象中的秒的数值,数值范围从1到59。
GetDayOfWeek:返回CTime对象中星期数,若为星期天,则返回1,星期一返回2,依次类推。
GetGmTm:将CTime对象中的信息分解为不同的部分,返回值为tm结构类型的指针。
Format:将CTime类对象中的时间信息转换为一个格式化的字符串,时间基于当地时区。
Format:设置字符串的内容,类似于sprintf格式化字符串。
TrimLeft:设置字符串的内容,类似于sprintf格式化字符串。
Find:在字符串中从头查找字符或字符串,返回值为第一个找到点位置的索引值。
GetBuffer:返回一个指向字符串内部字符缓冲区的指针,可设置缓冲区长度。
ReleaseBuffer:释放内部字符缓冲区指针的控制。
CStringArray:用来表示可变长度的字符串数组。数组中每一个元素为CString对象的实例。下面介绍几个成员函数:
Add 增加CString
RemoveAt 删除指定位置CString对象
RemoveAll 删除数组中所有CString对象
GetAt 得到指定位置的CString对象
SetAt 修改指定位置的CString对象
InsertAt 在某一位置插入CString对象
常用宏
RGB
TRACE
ASSERT
VERIFY
题1:
Char* name;
Char a[6] = {0};
name = a;
上面有错误吗?a = name;可以吗?
为什么?
题2:
String& getstring(){
String str;
While(cin>>str){
//............
}
//.................
Return str;
}
程序对吗?
题3:
struct sa
{
Long key;
Double value;
sa& operator = (const sa& src){
if(this != &src){
*this = sa;
}
Return *this;
};
为什么operator=操作符返回引用?
当前的operator=需要吗?
上面有错误吗?