关于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:两个函数的返回值都是线程的句柄。
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:两个函数的返回值都是线程的句柄。
相关文章推荐
- EF(Entity Framework)发生错误”正在创建模型,此时不可使用上下文“的解决办法。 正在创建模型,此时不可使用上下文。如果在 OnModelCreating 方法内使用上下文或如果多个线程同时访问同一上下文实例,可能引发此异常。请注意不保证 DbContext 的实例成员和相关类是线程安全的。 临时解决了这个问题,在Context的构造函数中,禁用了自动初始化:
- parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)VC以类的成员函数作为线程调用函数时易出错问题解决办法
- invoke委托解决“线程间操作无效: 从不是创建控件的线程访问它”的问题
- 多线程访问同一资源第二步 : 线程设置 以及 线程打印 用synchronized解决数据不匹配问题
- 线程间操作无效: 从不是创建控件“...”的线程访问它 问题解决
- 通过配置多个DispatcherServlet解决SpringMVC RESTAPI前后端分离资源访问的问题
- 关于“ASP.NET 无权访问所请求的资源”问题解决
- win32 API创建tooltip的版本不匹配问题解决方法
- 关于struts Validator在多模块下多国语言资源访问的问题解决之道(一)struts Validator下使用多模块的多国语言资源
- 关于调用线程无法访问此对象,因为另一个线程拥有该对象的问题的解决办法
- 【问题解决】线程间操作无效:从不是创建控件“textBox1”的线程访问它
- c#中使用多线程访问winform中控件的若干问题 解决线程间操作无效: 从不是创建控件的线程访问它
- 关于VS编译出现“从不是创建控件 control name 的线程访问它”问题的解决方案
- 4000 c#关于“线程间操作无效: 从不是创建控件的线程访问它”的问题
- 在VC中创建两套资源解决中英文版本发布的问题
- WinForm解决多线程操作控件问题 线程间操作无效: 从不是创建控件的线程访问它"
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~ 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析
- 关于在IIS中出现ASP.NET 未被授权访问所请求的资源问题的解决
- 解决“从不是创建控件的线程访问它”问题。
- 通过配置多个DispatcherServlet解决SpringMVC RESTAPI前后端分离资源访问的问题