tlsstat.c
来自「一本已经绝版的好书」· C语言 代码 · 共 250 行
C
250 行
/************************************************************
Module name: TLSStat.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
************************************************************/
#include "..\CmnHdr.H" /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdlib.h> // For rand
#include <stdio.h> // For sprintf
#include <process.h> // For _beginthreadex
#include "Resource.H"
/////////////////////////////////////////////////////////////
// Structure used to pass data from one thread to another
typedef struct {
int nThreadNum; // The number used for recordkeeping
int nNumCycles; // Number of iterations in the loop
DWORD dwCycleTime; // Time spent in each loop iteration
} THREADDATA, *LPTHREADDATA;
// Global handle to list box window used for
// logging execution
HWND g_hwndLogLB = NULL;
// Our global static TLS variable
// to hold each thread's start time
// The system will automatically allocate one of these
// for every thread created in this process.
__declspec(thread) DWORD gt_dwStartTime = 0;
/////////////////////////////////////////////////////////////
DWORD WINAPI ThreadFunc (LPVOID lpvThreadParm) {
// The parameter passed to us is a pointer to a THREADDATA
// structure. Let's save it in a local variable.
LPTHREADDATA lpThreadData = (LPTHREADDATA) lpvThreadParm;
TCHAR szBuf[100];
// Store the thread's start time in its very
// own static TLS variable.
gt_dwStartTime = GetTickCount();
// Write a log entry stating that we're starting.
_stprintf(szBuf, __TEXT("Thread started: %d"),
lpThreadData->nThreadNum);
ListBox_AddString(g_hwndLogLB, szBuf);
ListBox_SetCurSel(g_hwndLogLB, 0);
// Start doing some work....
while (lpThreadData->nNumCycles--) {
// Write to the log how many cycles this thread
// has left before it dies and how long this thread
// has been running.
_stprintf(szBuf,
__TEXT("Thread %d, Cycles left=%d, time running=%d"),
lpThreadData->nThreadNum, lpThreadData->nNumCycles,
GetTickCount() - gt_dwStartTime);
ListBox_AddString(g_hwndLogLB, szBuf);
// Sleep for awhile and let other threads run.
Sleep(lpThreadData->dwCycleTime);
}
// This thread is done executing; write a log entry
// that says so and displays the total execution time
// of the thread.
_stprintf(szBuf, __TEXT("Thread ended: %d, total time=%d"),
lpThreadData->nThreadNum,
GetTickCount() - gt_dwStartTime);
ListBox_AddString(g_hwndLogLB, szBuf);
// The thread is responsible for deleting the THREADDATA
// structure that was allocated by the primary thread.
HeapFree(GetProcessHeap(), 0, lpvThreadParm);
return(0);
}
/////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus,
LPARAM lParam) {
// Associate an icon with the dialog box.
chSETDLGICONS(hwnd, IDI_TLSSTAT, IDI_TLSSTAT);
// Default the thread number to 1.
SetDlgItemInt(hwnd, IDC_THREADNUM, 1, FALSE);
// Default the number of cycles to 10.
SetDlgItemInt(hwnd, IDC_NUMCYCLES, 10, FALSE);
// Default the maximum cycle time to 3 seconds.
SetDlgItemInt(hwnd, IDC_CYCLETIME, 3, FALSE);
// Save the handle of the dialog box in a global
// variable so that it can be accessed easily from
// the thread function.
g_hwndLogLB = GetDlgItem(hwnd, IDC_LOG);
// Let's start with the Create Thread
// button having focus.
SetFocus(GetDlgItem(hwnd, IDOK));
// I set focus, so the Dialog Manager shouldn't.
return(FALSE);
}
/////////////////////////////////////////////////////////////
void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtl,
UINT codeNotify) {
DWORD dwIDThread;
HANDLE hThread;
LPTHREADDATA lpThreadData;
switch (id) {
case IDC_CLEAR:
// Reset the application.
SetDlgItemInt(hwnd, IDC_THREADNUM, 1, FALSE);
ListBox_ResetContent(g_hwndLogLB);
break;
case IDOK:
// Allocate a block of memory that can be used to
// give data from this thread to the new thread we
// are about to create.
lpThreadData = (LPTHREADDATA)
HeapAlloc(GetProcessHeap(), 0,
sizeof(THREADDATA));
if (lpThreadData == NULL) {
// Memory could not be allocated; display message
// box and break.
chMB(__TEXT("Error creating ThreadData"));
break;
}
// Fill the memory block with the data from
// the dialog box.
lpThreadData->nThreadNum =
GetDlgItemInt(hwnd, IDC_THREADNUM, NULL, FALSE);
lpThreadData->nNumCycles =
GetDlgItemInt(hwnd, IDC_NUMCYCLES, NULL, FALSE);
// Multiply the cycle time by 1000
// to convert to seconds.
lpThreadData->dwCycleTime = (DWORD)
(1000 * GetDlgItemInt(hwnd,
IDC_CYCLETIME, NULL, FALSE));
// Increment the thread number for the next thread.
SetDlgItemInt(hwnd, IDC_THREADNUM,
lpThreadData->nThreadNum + 1, FALSE);
// Create the new thread and pass it the address of
// our allocated memory block containing the
// attributes that the thread should use. The
// thread is responsible for freeing the memory
// block when it no longer needs it.
hThread = chBEGINTHREADEX(NULL, 0, ThreadFunc,
(LPVOID) lpThreadData, 0, &dwIDThread);
if (hThread != NULL) {
// If the thread was created successfully, close
// the handle because this thread never needs
// to refer to the new thread again.
CloseHandle(hThread);
} else {
// The thread could not be created;
// display message box and break.
chMB(__TEXT("Error creating the new thread"));
HeapFree(GetProcessHeap(), 0,
(LPVOID) lpThreadData);
}
break;
case IDCANCEL:
EndDialog(hwnd, id);
break;
}
}
/////////////////////////////////////////////////////////////
BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
/////////////////////////////////////////////////////////////
int WINAPI _tWinMain (HINSTANCE hinstExe,
HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {
TCHAR szBuf[100];
chWARNIFUNICODEUNDERWIN95();
// The primary thread also gets its own TLS copy
// of the gt_dwStartTime variable. Let's initialize it to
// the time when the application started executing.
gt_dwStartTime = GetTickCount();
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_TLSSTAT),
NULL, Dlg_Proc);
// The user has terminated the dialog box; let's show
// how long the whole application has been running.
_stprintf(szBuf,
__TEXT("Total time running application=%d."),
GetTickCount() - gt_dwStartTime);
chMB(szBuf);
return(0);
}
//////////////////////// End Of File ////////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?