将 GetDC 代码移动到线程中时性能大幅下降
Great Performance Decreasement when Moving the GetDC code into a thread
下一题Strange Efficiency Decrease when Localizing a Global Variable into a Subthread,最近发现性能下降的问题其实是把GetDC的代码移到了线程里,本来是放在WindowProc/WndProc函数里的, 但我不知道细节。
谁能帮帮我?
毕竟,这是我的代码:
快一:
#include <stdio.h>
#include <math.h>
#include <windows.h>
#define num 4
#define width 1
double position[num][2] = {{733, 434}, {633, 384}, {733, 284}, {733, 684}};
double velocity[num][2] = {{-5, 2.5}, {5, -2.5}, {0, 2.5}, {10, -2.5}};
COLORREF color[num] = {0xffffff, 0x00ffff, 0x0000ff, 0xffff00};
COLORREF background_color = 0x000000;
double distance;
int count, i, j;
HDC hdc[num];
HPEN hpen[num];
inline double sqr(double x) {return x * x;}
DWORD WINAPI threadProc(LPVOID lpParamter) {
Sleep(1000);
while(1) {
for(i=0; i<num; ++i) {
LineTo(hdc[i], position[i][0], position[i][1]);
position[i][0] += velocity[i][0];
position[i][1] += velocity[i][1];
}
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR pCmdLine, int nCmdShow) {
const char *CLASS_NAME = "SUGEWND";
void *pHWND = &hInstance;
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, "SUGE",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(hwnd == NULL) return 0;
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
MSG msg={};
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc2=BeginPaint(hwnd, &ps);
FillRect(hdc2, &ps.rcPaint, CreateSolidBrush(background_color));
EndPaint(hwnd, &ps);
return 0;
}
case WM_CREATE: {
for(i=0; i<num; ++i) {
hdc[i] = GetDC(hwnd);
hpen[i] = CreatePen(PS_SOLID, width, color[i]);
SelectObject(hdc[i], hpen[i]);
MoveToEx(hdc[i], position[i][0], position[i][1], 0);
}
HANDLE hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL);
CloseHandle(hThread);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
慢一个:
#include <stdio.h>
#include <math.h>
#include <windows.h>
#define num 4
#define width 1
double position[num][2] = {{733, 434}, {633, 384}, {733, 284}, {733, 684}};
double velocity[num][2] = {{-5, 2.5}, {5, -2.5}, {0, 2.5}, {10, -2.5}};
COLORREF color[num] = {0xffffff, 0x00ffff, 0x0000ff, 0xffff00};
COLORREF background_color = 0x000000;
double simulate_acc = 0.00001;
double distance;
int count, i, j;
HDC hdc[num];
HPEN hpen[num];
inline double sqr(double x) {return x * x;}
DWORD WINAPI threadProc(LPVOID lpParamter) {
HWND hwnd = *(HWND*)lpParamter;
for(i=0; i<num; ++i) {
hdc[i] = GetDC(hwnd);
hpen[i] = CreatePen(PS_SOLID, width, color[i]);
SelectObject(hdc[i], hpen[i]);
MoveToEx(hdc[i], position[i][0], position[i][1], 0);
}
Sleep(1000);
while(1) {
for(i=0; i<num; ++i) {
LineTo(hdc[i], position[i][0], position[i][1]);
position[i][0] += velocity[i][0];
position[i][1] += velocity[i][1];
}
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR pCmdLine, int nCmdShow) {
const char *CLASS_NAME = "SUGEWND";
void *pHWND = &hInstance;
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, "SUGE",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(hwnd == NULL) return 0;
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
MSG msg={};
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc2=BeginPaint(hwnd, &ps);
FillRect(hdc2, &ps.rcPaint, CreateSolidBrush(background_color));
EndPaint(hwnd, &ps);
return 0;
}
case WM_CREATE: {
HANDLE hThread = CreateThread(NULL, 0, threadProc, &hwnd, 0, NULL);
CloseHandle(hThread);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
您正在将一个指向局部变量的指针传递给您的 threadProc
。从 WindowProc
退出后,它的局部变量不再有效。
您可以按值传递 HWND
:
case WM_CREATE: {
HANDLE hThread = CreateThread(NULL, 0, threadProc, (LPVOID)hwnd, 0, NULL);
CloseHandle(hThread);
return 0;
}
然后读取它的值:
DWORD WINAPI threadProc(LPVOID lpParamter) {
HWND hwnd = (HWND)lpParamter;
下一题Strange Efficiency Decrease when Localizing a Global Variable into a Subthread,最近发现性能下降的问题其实是把GetDC的代码移到了线程里,本来是放在WindowProc/WndProc函数里的, 但我不知道细节。
谁能帮帮我?
毕竟,这是我的代码:
快一:
#include <stdio.h>
#include <math.h>
#include <windows.h>
#define num 4
#define width 1
double position[num][2] = {{733, 434}, {633, 384}, {733, 284}, {733, 684}};
double velocity[num][2] = {{-5, 2.5}, {5, -2.5}, {0, 2.5}, {10, -2.5}};
COLORREF color[num] = {0xffffff, 0x00ffff, 0x0000ff, 0xffff00};
COLORREF background_color = 0x000000;
double distance;
int count, i, j;
HDC hdc[num];
HPEN hpen[num];
inline double sqr(double x) {return x * x;}
DWORD WINAPI threadProc(LPVOID lpParamter) {
Sleep(1000);
while(1) {
for(i=0; i<num; ++i) {
LineTo(hdc[i], position[i][0], position[i][1]);
position[i][0] += velocity[i][0];
position[i][1] += velocity[i][1];
}
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR pCmdLine, int nCmdShow) {
const char *CLASS_NAME = "SUGEWND";
void *pHWND = &hInstance;
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, "SUGE",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(hwnd == NULL) return 0;
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
MSG msg={};
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc2=BeginPaint(hwnd, &ps);
FillRect(hdc2, &ps.rcPaint, CreateSolidBrush(background_color));
EndPaint(hwnd, &ps);
return 0;
}
case WM_CREATE: {
for(i=0; i<num; ++i) {
hdc[i] = GetDC(hwnd);
hpen[i] = CreatePen(PS_SOLID, width, color[i]);
SelectObject(hdc[i], hpen[i]);
MoveToEx(hdc[i], position[i][0], position[i][1], 0);
}
HANDLE hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL);
CloseHandle(hThread);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
慢一个:
#include <stdio.h>
#include <math.h>
#include <windows.h>
#define num 4
#define width 1
double position[num][2] = {{733, 434}, {633, 384}, {733, 284}, {733, 684}};
double velocity[num][2] = {{-5, 2.5}, {5, -2.5}, {0, 2.5}, {10, -2.5}};
COLORREF color[num] = {0xffffff, 0x00ffff, 0x0000ff, 0xffff00};
COLORREF background_color = 0x000000;
double simulate_acc = 0.00001;
double distance;
int count, i, j;
HDC hdc[num];
HPEN hpen[num];
inline double sqr(double x) {return x * x;}
DWORD WINAPI threadProc(LPVOID lpParamter) {
HWND hwnd = *(HWND*)lpParamter;
for(i=0; i<num; ++i) {
hdc[i] = GetDC(hwnd);
hpen[i] = CreatePen(PS_SOLID, width, color[i]);
SelectObject(hdc[i], hpen[i]);
MoveToEx(hdc[i], position[i][0], position[i][1], 0);
}
Sleep(1000);
while(1) {
for(i=0; i<num; ++i) {
LineTo(hdc[i], position[i][0], position[i][1]);
position[i][0] += velocity[i][0];
position[i][1] += velocity[i][1];
}
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR pCmdLine, int nCmdShow) {
const char *CLASS_NAME = "SUGEWND";
void *pHWND = &hInstance;
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, "SUGE",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(hwnd == NULL) return 0;
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
MSG msg={};
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc2=BeginPaint(hwnd, &ps);
FillRect(hdc2, &ps.rcPaint, CreateSolidBrush(background_color));
EndPaint(hwnd, &ps);
return 0;
}
case WM_CREATE: {
HANDLE hThread = CreateThread(NULL, 0, threadProc, &hwnd, 0, NULL);
CloseHandle(hThread);
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
您正在将一个指向局部变量的指针传递给您的 threadProc
。从 WindowProc
退出后,它的局部变量不再有效。
您可以按值传递 HWND
:
case WM_CREATE: {
HANDLE hThread = CreateThread(NULL, 0, threadProc, (LPVOID)hwnd, 0, NULL);
CloseHandle(hThread);
return 0;
}
然后读取它的值:
DWORD WINAPI threadProc(LPVOID lpParamter) {
HWND hwnd = (HWND)lpParamter;