您的位置:首页 > 其它

关于Win32 API(VC作为程序设计语言)的创建线程,解决互斥访问临界资源问题

2010-03-19 23:45 666 查看
此工程在4月份被更改,下面的是初级试验阶段的产物。不过能够进行一些交流。

2010-03-19 23:46:39

首先是工程(名为supper),在VC++6.0下是Windows Application,dsw文件的写法:

Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

###############################################################################

Project: "supper"="./supper.dsp" - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Global:

Package=<5>
{{{
}}}

Package=<3>
{{{
}}}

###############################################################################

随后是头文件:

/************************************
* 文 件 信 息 *
* File Infomation *
* *
*文件名称 : supper.h *
*File Name : supper.h *
*文件作者 : Woody.c *
*File Athour : Woody.c *
*文件最初版本 : 1.1版 *
*Create Edition : version 1.1 *
*文件创建时间 : 2010年3月19日 *
*Create Date : 2010年3月19日 *
*当前版本 : 1.1版 *
*Current Editon : version 1.1 *
*最后一次修改 : 2010年3月19日 *
*Last Modify : 2010年3月19日 *
* *
*************************************/

#ifndef ___SUPPER___H___
#define ___SUPPER___H___

//加载支持:
#include <windows.h>
#include <time.h>
#include <process.h>

//宏定义:
//版本
#define EDITION "Supper v1.1"
#define MAXTHINKER 5 //思考者人数

//Sub声明:
//主入口函数WinMain()
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow);
//消息处理函数WndProc()
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
//动作线程
VOID Thread(PVOID pvoid);
//筷子校验线程(可屏蔽)
VOID TestChop(PVOID pvoid);
//吃动作
void Eat(HDC hdc, int id, char * szName);
//思考动作
void Think(HDC hdc, int id, char * szName);

//示例函数Example()
//void Example(void);

//全局变量:
HWND hwnd;
int cxClient, cyClient;
int GnChops[MAXTHINKER] = {1, 1, 1, 1, 1}; //筷子的信息量
char GszName[5][20] = {"Einstein", "Plato", "Marx", "Confusious", "Galie"}; //姓名
static int nID;

#endif

随后是源文件,小工程单文件搞定:

/************************************
* 文 件 信 息 *
* File Infomation *
* *
*文件名称 : supper.c *
*File Name : supper.c *
*文件作者 : Woody.c *
*File Athour : Woody.c *
*文件最初版本 : 1.1版 *
*Create Edition : version 1.1 *
*文件创建时间 : 2010年3月19日 *
*Create Date : 2010年3月19日 *
*当前版本 : 1.1版 *
*Current Editon : version 1.1 *
*最后一次修改 : 2010年3月19日 *
*Last Modify : 2010年3月19日 *
* *
*************************************/
#include "supper.h"

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT(EDITION);
HWND hwnd;
MSG msg;
WNDCLASS wndclass;

wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclass.lpszMenuName = NULL; //TEXT("IDR_MENU_EXAMPLE");
wndclass.lpszClassName = szAppName;

if(!RegisterClass(&wndclass))
{
MessageBox (NULL, TEXT("This program requires Windows NT!"),szAppName, MB_ICONERROR);
return 0;
}

hwnd = CreateWindow(szAppName, TEXT(EDITION), WS_POPUP,
100, 100, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

ShowWindow (hwnd,SW_SHOWMAXIMIZED);
UpdateWindow(hwnd);

srand((unsigned)time(NULL));

while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam ;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps; //绘图结构体
HDC hdc; //设备句柄handle of device
HDC hdcMem; //同上
static HINSTANCE hInstance; //静态HINSTANCE,表示当前实例。
// HFONT hfont;

switch(message)
{
//窗口的创建:
case WM_CREATE:
hInstance = ((LPCREATESTRUCT)lParam) -> hInstance; //由传入消息的参数得到当前实例

//开始线程
_beginthread(Thread, 0, NULL);
_beginthread(Thread, 0, NULL);
_beginthread(Thread, 0, NULL);
_beginthread(Thread, 0, NULL);
_beginthread(Thread, 0, NULL);
_beginthread(TestChop, 0, NULL);

return 0 ;

case WM_SIZE:
cxClient = LOWORD(lParam) ;
cyClient = HIWORD(lParam) ;
return 0 ;

case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
case VK_SPACE:
PostQuitMessage (0) ;
break;
default:
break;
}
return 0;

case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
PostQuitMessage (0) ;
return 0;

case WM_PAINT:
//开始绘图
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
hdc = BeginPaint(hwnd, &ps);
hdcMem = CreateCompatibleDC(hdc); //创建一个与指定设备一致的内存设备描述表

DeleteDC(hdcMem); //绘画动作结束,删除内存设备描述表
EndPaint(hwnd, &ps);

return 0 ;

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

VOID Thread(PVOID pvoid)
{
static int nX = 0;
int nID = nX++;
HDC hdc;
HFONT hFont;

hdc = GetDC(hwnd);
hFont = CreateFont(40, 40, 0, 0, 0, 0, 0, 0,
GB2312_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH & FF_DONTCARE, "黑体");
SelectObject(hdc, hFont);

while(1)
{
//对左右两方向筷子进行观察,如果都可得才拿起
if(GnChops[nID] > 0 && GnChops[(nID + 1) % MAXTHINKER] > 0)
{
//加锁,即修改信息量,标志左右两筷子被占用
GnChops[nID] = GnChops[nID] - 1;
GnChops[(nID + 1) % MAXTHINKER] = GnChops[(nID + 1) % MAXTHINKER] - 1;
SetTextColor(hdc, RGB(200,100,200));
//执行吃动作(产生延迟)
Eat(hdc, nID, GszName[nID]);
//解锁,释放筷子的被占用状态
GnChops[nID] = GnChops[nID] + 1;
GnChops[(nID + 1) % MAXTHINKER] = GnChops[(nID + 1) % MAXTHINKER] + 1;
//恢复思考,吃饱了,好好干!
SetTextColor(hdc, RGB(100, 200, 200));
Think(hdc, nID, GszName[nID]);
}
else//至少有一根筷子不可得
{
//继续思考
SetTextColor(hdc, RGB(100, 200, 200));
Think(hdc, nID, GszName[nID]);
}
}
//释放开辟的字体
DeleteObject(hFont);
ReleaseDC(hwnd, hdc);
_endthread();
}

VOID TestChop(PVOID pvoid)
{
int i;
HDC hdc;
HBRUSH hBrush;

hdc = GetDC(hwnd);

while(1)
{
for(i = 0; i < MAXTHINKER; i++)
{
if(GnChops[i] > 0)
{
hBrush = GetStockObject(BLACK_BRUSH);
}
else
{
hBrush = GetStockObject(WHITE_BRUSH);
}
SelectObject(hdc, hBrush);
Rectangle(hdc, i * 100 + 200, 150, i * 100 + 200 + 20, 170);
DeleteObject(hBrush);
}
}
ReleaseDC(hwnd, hdc);
_endthread();
}

void Eat(HDC hdc, int id, char * szName)
{
int i;
char szOutput[30];

strcpy(szOutput, szName);
strcat(szOutput, " is Eating !!!! ");
TextOut(hdc, 200, 200 + id * 50, szOutput, strlen(szOutput));

i = rand()%1123 + 2131;
Sleep(i);
}

void Think(HDC hdc, int id, char * szName)
{
int i;
char szOutput[30];

strcpy(szOutput, szName);
strcat(szOutput, " is Thinking! ");
TextOut(hdc, 200, 200 + id * 50, szOutput, strlen(szOutput));

i = rand()%1321 + 1231;
Sleep(i);
}

注释比较少。这个完成的工作是解决“五个哲学家进餐问题”

自我记录:线程的创建,在process.h头文件下,据我所知有两种形式:

uintptr_t _beginthread(
void( __cdecl *start_address )( void * ), //目标函数指针
unsigned stack_size, //堆栈容量,若不需要则写0
void *arglist //传入目标函数的参数,void *类型,可以自己构造结构体
);
uintptr_t _beginthreadex(
void *security, //形式,这个比较麻烦,参见MSDN解CreateThread()
unsigned stack_size, //同样是堆栈容量
unsigned ( __stdcall *start_address )( void * ), //目标函数指针
void *arglist, //传入目标函数的参数
unsigned initflag, //可为CREATE_SUSPENDED或0,前者进程被创建后默认为挂起
unsigned *thrdaddr //进程ID的地址
);

一般我个人选用前者,参数少使用方便,但是切记在最后加“_endthread();”来完成对线程的释放,避免造成不必要的资源泄露问题。

第二个函数参数多,功能也相对强大,可以阻塞创建的线程1,而且也可以传出线程ID。

P.S:两个函数的返回值都是线程的句柄。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐