本篇文章主要介绍了"windows多线程编程 windows多线程编程星球(一)",主要涉及到windows多线程编程方面的内容,对于Windows 7jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播感兴趣的同学可以参考一下:
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分。原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这...
void PlanetSpin(const struct Planet &p,int spinInterval,int picType)
{
char spin[4] = {'|','/','-','\\'};
if( p.type == 1 )
{
MoveOutputToPos(0,0,&spin[picType%4],false);
MoveOutputToPos(0,1,&spin[picType%4],false);
MoveOutputToPos(1,0,&spin[picType%4],false);
MoveOutputToPos(1,1,&spin[picType%4],false);
::Sleep(spinInterval);
}
else
{
...
}
}
else部分的代码后面再说明,大体意思就是让一个planet以某一个间隔旋转(spinInterval),其实也就是刷新时间,其中我把所有和在dos窗口中指定地点输出指定图形的内容分离出来用一个单独的函数,因为这部分在后面使用的还是挺频繁的并且会让我们遇到多线程编程的第一个重要知识点。MoveOutputToPos前两个参数是DOS窗口的横坐标和纵坐标,第三个是输出的字符,最后一个是为了后面输出string准备的,第一版代码大体是下面这个样子的,用到的还是console api。
void MoveOutputToPos(int x,int y,char* c,bool bString)
{
csbiInfo.dwCursorPosition.X = x;
csbiInfo.dwCursorPosition.Y = y;
if (!SetConsoleCursorPosition(hOut,csbiInfo.dwCursorPosition))
{
printf("SetConsoleCursorPosition error!!!!! \r\n");
return;
}
if(!bString)
printf("%c",c[0]);
else
printf("%s",c);
}
二、分离星球。
母星的第一个作用是分离出子星球,既然是子星球这么直白朴实的名字,我相信你也猜到了,我就是用这个表示子线程。一个子星球在线程世界里面就是一个独立的,但是又和母星有关联的个体,这也符合线程的基本特点。同样子星球也有资源属性并且都和母星球共用一个资源库,而且也会旋转。但是毕竟他不完全是母星球,还是有一点不同的,子星球可以前进。既然文章主要是介绍多线程,那么我们就从创建一个子星球来开始第一个多线程相关的函数。
HANDLE hThread1 = CreateThread(0, // SECURITY_ATTRIBUTES, 线程的安全属性,可以写一个专门的主题,0表示默认值
16 * 1024L, //为线程分配的堆栈大小,会在最后特别提一下这个,在PC上没啥感觉,但是我在嵌入式上经常被坑
ThreadProc, //线程执行函数,也就是你具体需要这个线程干嘛
&Planet1, //主线程传给线程函数的参数(地址块)
0, //一些标志位,比如你可以创建一个线程不让他立即执行
NULL);//返回线程id,如果你需要,可以定义一个dword,在这个函数调用成功后会写入线程的id
看到上面的函数,不得不自然说的是这个第三个参数,threadproc,这个参数的定义类型是”_In_ LPTHREAD_START_ROUTINE lpStartAddress”,_In_表示是一个输入值,中间这个LPTHREAD_START_ROUTINE是一个函数指针,定义如下:
typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) (
[in] LPVOID lpThreadParameter
);
这个看起来超级复杂的式子其实就是指向一个返回值是dword并且没有参数的函数的一个指针,本质上是一个地址,所以用lpStartAddress作为参数的名字。有了这个说明,所以ThreadProc的函数原型一定是这样的了:
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
在这个ThreadProc函数里面,目前只让子星球做两件事情,前进和旋转。而前进的动力来自于资源,但是你会发现貌似以目前介绍过的函数,你还没有办法控制这个资源和母星球资源之间的增减,所以我就先简单的假设子星球创建出来之后其资源是可以自己获取自己增加,这样他就可以不断的前进了。
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
struct Planet* p = (struct Planet*)lpParameter;
int nSpinType = 0;
while(true)
{
PlanetMove(*p);
PlanetSpin(*p,500,nSpinType);
nSpinType++;
}
return 1;
}
void PlanetMove(struct Planet &p)
{
char cLine[100];
memset(cLine,0,100*sizeof(char));
if( p.resource < nMaxResource-1 )
{
p.resource++;
memset(cLine,'-',p.resource*sizeof(char));
MoveOutputToPos(0,p.index*3+1,cLine,true);
}
}
到这里,我们就可以补足PlanetSpin里面else的那一部分了,这一部分是为给子星球写的旋转代码。
else
{
char sep = '*';
MoveOutputToPos(0,p.index*3-1,&sep,false);
MoveOutputToPos(0,p.index*3,&sep,false);
MoveOutputToPos(p.resource,p.index*3+1,&spin[picType%4],false);
::Sleep(spinInterval);
}
目前看来,我们已经可以自由的创建出一个星球,事实上,只要你愿意,你可以创建出多个。但是为了不要让问题搞的特别复杂,我还是先限定为一个。目前创建出来的星球一个最大的特点是不听使唤无法控制,你无法控制它前进与否,旋转与否,什么时候开始启动等等。因为一旦你仅仅是创建一个线程,你能对它做的很少很少。刚创建出来的线程就像一个熊孩子,无法控制,你得通过一些手段和方法来让它能够听从主线程的指挥或者和主线程互动。这也是后面慢慢要写的内容,也是多线程编程的核心内容了。