CreateThread函数&&CString::GetBuffer函数
对这个两个常见的windows下的函数学习了一下:
//最简单的创建多线程实例 #include <stdio.h> #include <windows.h> //子线程函数 DWORD WINAPI ThreadFun(LPVOID pM) { printf("子线程的线程ID号为:%d\n子线程输出Hello World\n", GetCurrentThreadId()); ; } //主函数,所谓主函数其实就是主线程执行的函数。 int main() { printf(" 最简单的创建多线程实例\n"); printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); HANDLE handle = CreateThread(NULL, , ThreadFun, NULL, , NULL); WaitForSingleObject(handle, INFINITE); ; }
第一个 CreateThread
函数功能:创建线程
函数原型:
HANDLE WINAPI CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
函数说明:
第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。
第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。
第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
第四个参数是传给线程函数的参数。
第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
函数返回值:
成功返回新线程的句柄,失败返回NULL。
第二个 WaitForSingleObject
函数功能:等待函数 – 使线程进入等待状态,直到指定的内核对象被触发。
函数原形:
DWORD WINAPI WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
函数说明:
第一个参数为要等待的内核对象。
第二个参数为最长等待的时间,以毫秒为单位,如传入5000就表示5秒,传入0就立即返回,传入INFINITE表示无限等待。
因为线程的句柄在线程运行时是未触发的,线程结束运行,句柄处于触发状态。所以可以用WaitForSingleObject()来等待一个线程结束运行。
函数返回值:
在指定的时间内对象被触发,函数返回WAIT_OBJECT_0。超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。传入参数有错误将返回WAIT_FAILED
CreateThread()函数是Windows提供的API接口,在C/C++语言另有一个创建线程的函数_beginthreadex(),在很多书上(包括《Windows核心编程》)提到过尽量使用_beginthreadex()来代替使用CreateThread(),
原因:_beginthreadex()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准C运行库函数如strtok()时就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据而不会去篡改其它线程的数据了。因此,如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread()
getbuffer是为了让你使用CString类中,保存字符串缓冲区的那块指针.
至于releasebuffer,在MSDN中有这样一句话.
If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.
在对GetBuffer返回的指针使用之后需要调用ReleaseBuffer,这样才能使用其他Cstring的operations。否则会发生错误.
GetBuffer(0)返回的是指向CString对象所构造的字串指针,为GetBuffer(0)由系统自动计算字串所要的空间长度,但要求是规则的含\0字串,否则得自己给出长度,如str.GetBuffer(20)。
LPTSTR GetBuffer( int nMinBufLength ) 这个函数是CString 的一个比较实用的函数,请看如下示例:
GetBuffer(int nMinBufLength);的参数问题一直比较困扰人,网站的资料还像也不是太好给的,请看msdn解释
Parameters
nMinBufLength
The minimum size of the character buffer in characters. This value does not include space for a null terminator.
得到buffer的最小长度,当然这是由我们自己设定的一个参数,其原型定义如下:
LPTSTR CString::GetBuffer(int nMinBufLength)
{
ASSERT(nMinBufLength >= 0);
if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
{
#ifdef _DEBUG
// give a warning in case locked string becomes unlocked
if (GetData() != _afxDataNil && GetData()->nRefs < 0)
TRACE0("Warning: GetBuffer on locked CString creates unlocked CString!/n");
#endif
// we have to grow the buffer
CStringData* pOldData = GetData();
int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
if (nMinBufLength < nOldLen)
nMinBufLength = nOldLen;
AllocBuffer(nMinBufLength);
memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
GetData()->nDataLength = nOldLen;
CString::Release(pOldData);
}
ASSERT(GetData()->nRefs <= 1);
// return a pointer to the character storage for this string
ASSERT(m_pchData != NULL);
return m_pchData;
}
上面的代码已经比较清楚了,当设定的长度小于原字符串长度时,nMinBufLength = nOldLen,然后分配相应的内存,当你设定的长度大于原字符串本身的长度时就要分配一块比较大的空间出来,这时你可以实现字符串对接的操作。
GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。
CString ::GetBuffer有两个重载版本:
LPTSTR GetBuffer( );LPTSTR GetBuffer(int nMinBufferLength);
在第二个版本中,当设定的长度小于原字符串长度时,nMinBufLength = nOldLen,该参数会被忽
略,不分配内存,指向原CString;当设定的长度大于原字符串本身的长度时就要重新分配(reallocate)一块比较大的空间出来。而调用第一个版本时,应如通过传入0来调用第二个版本一样。
是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不调用ReleaseBuffer没什么意义了。
这是一个非常容易被用错的函数,主要可能是由于大家对它的功能不太了解。其实点破的话,也不是那么深奥。
GetBuffer(int size)是用来返回一个你所指定大小可写内存的成员方法。它和被重载的操作符LPCTSTR还是有点本质区别的,LPCTSTR是直接返回一个只读内存的指针,而GetBuffer则是返回一个可以供调用者写入的内存,并且,你可以给定大小。下面是个简单的,但也是非常典型的例子:
int readFile(CString& str, const CString& strPathName)
{
FILE* fp = fopen(strPathName, "r"); // 打开文件
fseek(fp, 0, SEEK_END);
int nLen = ftell(fp); // 获得文件长度
fseek(fp, 0, SEEK_SET); // 重置读指针
char* psz = str.GetBuffer(nLen);
fread(psz, sizeof(char), nLen, fp); //读文件内容
str.ReleaseBuffer(); //千万不能缺少
fclose(fp);
}
上面的函数是GetBuffer函数最典型的用法了,其实它就相当于申请一块nLen大小的内存,只不过,这块内存是被引用在CString对象的内部而已,这是非常有效的一种用法,如果不直接用GetBuffer函数来申请的话,那么你必须用new操作符(或者malloc()函数)在CString的外部申请,然后再将申请的内存拷贝到CString对象中,显然这是一个非常冗余的操作,会使你函数的效率大大下降。
ReleaseBuffer函数是用来告诉CString对象,你的GetBuffer所引用的内存已经使用完毕,现在必须对它进行封口,否则 CString将不会知道它现在所包含的字符串的长度,所以在使用完GetBuffer之后,必须立即调用ReleaseBuffer函数重置 CString的内部属性,其实也就是头部信息。
补充一下:
GetBuffer说白了就两个功能:
1:就是将CString里面的内存交到外部一个来处理,外部可以直接修改它的内容。
2:重新修改CString的内存大小,这个数值不包含null结尾符。
另一个典型的用法:就是将CString里面的内容变为int或long型,需要先获取里面的内存指针。这样就可以先GetBuffer(内存大小)方便直接转换。
如果在外部修改了CString里面的内容,在重新使用CString之前,需调用ReleaseBuffer()也就是说,ReleaseBuffer不需要每次都调用。
MSDN原文:
If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CSimpleStringT member methods.
The buffer memory is automatically freed when the CSimpleStringT object is destroyed.
If you keep track of the string length yourself, you should not append the terminating null character. You must, however, specify the final string length when you release the buffer with ReleaseBuffer. If you do append a terminating null character, you should pass –1 (the default) for the length toReleaseBuffer, and ReleaseBuffer will perform a strlen on the buffer to determine its length.
CreateThread函数&&CString::GetBuffer函数的更多相关文章
- CreateThread函数&&CString::GetBuffer函数
对这个两个常见的windows下的函数学习了一下: //最简单的创建多线程实例 #include <stdio.h> #include <windows.h> //子线程函数 ...
- Sql Server函数全解<二>数学函数
阅读目录 1.绝对值函数ABS(x)和返回圆周率的函数PI() 2.平方根函数SQRT(x) 3.获取随机函数的函数RAND()和RAND(x) 4.四舍五入函数ROUND(x,y) 5.符号函数SI ...
- Sql Server函数全解<一>字符串函数
阅读目录 1.ASCII()函数 2.CHAR()函数 3.LEFT()函数 4.RIGHT()函数 5.LTRIM()函数 6.RTRIM()函数 7.STR()函数 8.字符串逆序的函数REVER ...
- JS函数 -- 功能,语法,返回值,匿名函数,自调用匿名函数,全局变量与局部变量,arguments的使用
“JavaScript设计得最出色的就是它的函数的实现.” -- <JavaScript语言精粹> 函数包含一组语句,它们是JS的基础模块单元,用于指定对象的行为.一般来说,所谓编程,就是 ...
- Sql Server函数全解(一)字符串函数
字符串函数用于对字符和二进制字符进行各种操作 1.ASCII()函数 ASCII(character_expression)函数用于返回字符串表达式中最左侧的ASCII代码值.参数character ...
- js中的全局变量和静态变量的使用, js 的调试?- 如果js出错, js引擎 就会停止, 这会 导致 后面的 html中 refer 该函数时, 会报错 函数为定义!!
效果里面的函数, 如show, hide,slideDown等, 这些都叫 "效果"函数, 但是里面可以包含动画, 也可以 不包含动画. 动画,是指 元素 的内容 是 逐渐 显示/ ...
- 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数009,Measure,测量函数
<zw版·Halcon-delphi系列原创教程> Halcon分类函数009,Measure,测量函数 为方便阅读,在不影响说明的前提下,笔者对函数进行了简化: :: 用符号“**”,替 ...
- C++调用动态库中的虚基类成员函数时总是进错函数
原创文章,转载请注明作者与本文原始URL. 问题描述:最近遇到这样一个问题,在调用C++的一个成员函数时,总是进错函数.在调用 pMsg->GetMsgContent() 的时候,总是进入到 p ...
- jQuery1.11源码分析(9)-----初始化jQuery对象的函数和关联节点获取函数
这篇也没什么好说的,初始化jQuery对象的函数要处理多种情况,已经被寒冬吐槽烂了.关联节点获取函数主要基于两个工具函数dir和sibling,前者基于指定的方向遍历,后者则遍历兄弟节点(真的不能合并 ...
随机推荐
- scanf()函数用法小结
scanf()函数是格式化输入函数,它从标准输入设备(键盘) 读取输入的信息. 其调用格式为: scanf("<格式化字符串>",<地址表>); ...
- linux服务器下发送邮件
系统管理人员经常会遇到对于设备或者任务的预警与通知,通常情况有发送短信.邮件等方式.发送短信一般来说需要有短信猫(硬件)或者调用libfetion给飞信用户发送.本文介绍几种简单的发送邮件的方式. 本 ...
- Hibernate逍遥游记-第4章映射对象标识符-increment、identity、hilo、native、assigned、sequence、<meta>
1. package mypack; import java.lang.reflect.Constructor; import org.hibernate.*; import org.hibernat ...
- iOS xcuserdata
说明: project.xcworkspace说明:is a directory of files describing the workspace or projects. Althou ...
- 显示Servlet API主要版本,次要版本以及服务器系统信息
package com.mhb; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Servle ...
- SAP 物料基本单位与BOM单位
比如:物料的基本单位是G,可该物料放到BOM中的单位却是PC,该如何实现呢? 1. 首先要弄清楚BOM单位优先取的是发货单位(工厂数据视图1),当发货单位为空时,取基本单位: 2. 然后再建立单位G ...
- Oracle数据库ORA-12154: TNS: 无法解析指定的连接标识符详解
ORA-12154: TNS: 无法解析指定的连接标识符(转自http://www.cnblogs.com/psforever/p/3929064.html) 相信使用过Oracle数据库的人一定碰到 ...
- 修练8年C++面向对象程序设计之体会
http://pcedu.pconline.com.cn/empolder/gj/c/0504/609482_1.html
- Doubango ims 框架 分析之 多媒体部分
序言 RTP提供带有实时特性的端对端数据传输服务,传输的数据如:交互式的音频和视频.那些服务包括有效载荷类型定义,序列号,时间戳和传输监测控制.应用程序在UDP上运行RTP来使用它的多路技术和chec ...
- FZU 1591 Coral的烦恼
Problem Description 程序设计课的老师给Coral布置了一道题:用T(n)表示所有能整除n的正整数之和,对于给定的数字n,记S(n)=T(1)+T(2)+…+ T(n).你的任务就是 ...