[Win32]线程同步-Ocrosoft
浙江财经大学
信工学院ACM集训队

[Win32]线程同步

本文由 Ocrosoft 于 2018-06-20 19:17:15 发表

线程的内容好少…

当有一个大作业的时候,新开一个线程进行处理,任务完成的时候,通知主线程(事件信号)。

Thread1中的pparams变量被定义为volatile,表示即使只是读变量的地方,pparams的值也可能发生变化。
否则编译器在for循环处发现没有对pparams进行赋值操作,从而优化掉for条件中的pparams->bContinue检查。

#include <windows.h>
#include <math.h>
#include <process.h>

#define REP 10000000

#define STATUS_READY	0
#define STATUS_WORDKING	1
#define STATUS_DONE		2

#define WM_CALC_DONE	(WM_USER + 0)
#define WM_CALC_ABORTED	(WM_USER + 1)

typedef struct
{
	HWND hwnd;
	BOOL bContinue;
}
PARAMS, *PPARAMS;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT("BigJob1");
	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;
	wndclass.lpszClassName = szAppName;

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

	hwnd = CreateWindow(szAppName, TEXT("Multithreading Demo"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

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

void Thread(PVOID pvoid)
{
	double A = 1.0;
	INT i;
	LONG lTime;
	volatile PPARAMS pparams;

	pparams = (PPARAMS)pvoid;

	lTime = GetCurrentTime();
	// 完成REP次计算,或者被终止
	for (i = 0; i < REP && pparams->bContinue; i++)
		A = tan(atan(exp(log(sqrt(A*A))))) + 1.0;

	// 检查是否完成了REP次计算
	if (i == REP)
	{
		lTime = GetCurrentTime() - lTime;
		// 发送完成消息
		SendMessage(pparams->hwnd, WM_CALC_DONE, 0, lTime);
	}
	else
		// 发送中止消息
		SendMessage(pparams->hwnd, WM_CALC_ABORTED, 0, 0);

	_endthread();
}

LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static INT iStatus;
	static LONG lTime;
	static PARAMS params;
	static TCHAR *szMessage[] =
	{
		TEXT("Ready(left mouse bottom begins)"),
		TEXT("Working (right mouse button ends)"),
		TEXT("%d repetitions in %ld.msec")
	};

	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;
	TCHAR szBuffer[64];

	switch (message)
	{
	case WM_LBUTTONDOWN:
		if (iStatus == STATUS_WORDKING)
		{
			MessageBeep(0);
			return 0;
		}

		iStatus = STATUS_WORDKING;

		params.hwnd = hwnd;
		params.bContinue = TRUE;

		_beginthread(Thread, 0, &params);

		InvalidateRect(hwnd, NULL, TRUE);
		return 0;

	case WM_RBUTTONDOWN:
		// 右键中止
		params.bContinue = FALSE;
		return 0;

	case WM_CALC_DONE:
		lTime = lParam;
		iStatus = STATUS_DONE;
		InvalidateRect(hwnd, NULL, TRUE);
		return 0;

	case WM_CALC_ABORTED:
		iStatus = STATUS_READY;
		InvalidateRect(hwnd, NULL, TRUE);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);

		GetClientRect(hwnd, &rect);

		wsprintf(szBuffer, szMessage[iStatus], REP, lTime);
		DrawText(hdc, szBuffer, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

		EndPaint(hwnd, &ps);
		return 0;

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

欢迎转载,请保留出处与链接。Ocrosoft » [Win32]线程同步

点赞 (1)or拍砖 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址