Разное поведение программы на Win7 и WinXP

364
17 февраля 2017, 03:09

Есть такой код (минимальный рабочий пример):

#include <windows.h>
#include <cstdint>
HDC hDC; 
HDC  hDCMem;
HBITMAP hbitmap;
HWND  hwnd; 
int ScreenMaxX;
int ScreenMaxY;
short pattern[8]={~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF, ~0xFF};
HBRUSH brush=::CreatePatternBrush(::CreateBitmap(8, 8, 1, 1, pattern));
void bar(int nLeft, int nTop, int nRight, int nBottom)
{
    RECT rect;
    rect.left   = nLeft;
    rect.right  = nRight;
    rect.top    = nTop;
    rect.bottom = nBottom;
    ::SetTextColor(hDCMem, 0xFF00FF);
    ::SetBkColor(hDCMem, 0xFF00FF);
    //brush=::CreatePatternBrush(::CreateBitmap(8, 8, 1, 1, pattern));
    ::FillRect(hDCMem, &rect, brush);
}
void flush(){
    ::BitBlt(hDC, 0, 0, ScreenMaxX, ScreenMaxY, hDCMem, 0, 0, SRCCOPY);
}
CRITICAL_SECTION graphics_cs;
uint8_t thread_cnt=0;
uint8_t total_threads=2;
HANDLE turnstile1=CreateSemaphoreW(nullptr, 0, 2, nullptr);
void thread_func(int num){
    int x,y;
    if(num==0){
        x=20; y=0;
    } else {
        x=110; y=0;
    }
    while(true) {
        while(true) {
            EnterCriticalSection(&graphics_cs);
            if (thread_cnt == num) {
                thread_cnt++;
                bar(x, y, x+40, y+40);
                y+=1;
                //flush();
                if(thread_cnt==total_threads){
                    thread_cnt = 0;
                    flush();
                    ReleaseSemaphore(turnstile1, total_threads, nullptr);
                }
                LeaveCriticalSection(&graphics_cs);
                break;
            } else {
                LeaveCriticalSection(&graphics_cs);
            }
        }
        WaitForSingleObject(turnstile1, INFINITE);
        Sleep(100);
    }
}
void mainx ()
{
    InitializeCriticalSection(&graphics_cs);
    for(int i=0; i<total_threads; i++){
        CreateThread (nullptr, 0, (LPTHREAD_START_ROUTINE)thread_func, (LPVOID)i, 0, nullptr);
    }
}
DWORD Th(LPVOID param) // новая нить
{
    (void)param;
    ::SetWindowPos(hwnd, HWND_TOP,  // дескриптор окна и порядок размещения
                   10,   // позиция по-горизонтали
                   10,  // по-вертикали
                   400,  // ширина
                   500,  // высота
                   SWP_SHOWWINDOW  // отобразить
    );
    mainx();
    flush();
    return 0;
}
DWORD g_nMainThreadID;
//обработка сообщений главного окна приложения
long FAR PASCAL WindowProc(HWND   hWnd,UINT   message, WPARAM wParam,LPARAM lParam )
{
    switch (message)
    {
        case WM_PAINT:   flush();
            break;
        case WM_DESTROY: PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR  lpCmdLine,  int  nShowCmd )
{
    (void)hPrevInstance, (void)lpCmdLine;
    WNDCLASS  wc;
    MSG       msg;
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WindowProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = NULL;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = "Menu_one";
    wc.lpszClassName = "NAME";
    if (!RegisterClass(&wc)) {return 0; };

    //создаем главное окно приложения
    hwnd = CreateWindow("NAME",               // имя класса окна
                        "!",                // заголовок окна
                        WS_OVERLAPPEDWINDOW,  // стиль окна
                        CW_USEDEFAULT,        //р-ры и расположение по-умолчанию
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        HWND_DESKTOP,          // идентификатор родительского окна
                        NULL,                  // идентификатор меню
                        hInstance,             // идентификатор приложения
                        NULL                   // доп параметры
    );
    ScreenMaxX = ::GetSystemMetrics(SM_CXSCREEN);
    ScreenMaxY = ::GetSystemMetrics(SM_CYSCREEN);
    hDC = ::GetDC(hwnd);
    hDCMem  = ::CreateCompatibleDC(hDC);
    hbitmap = ::CreateCompatibleBitmap(hDC, ScreenMaxX, ScreenMaxY );
    ::SelectObject(hDCMem, hbitmap);
    auto hbrush = (HBRUSH)::GetStockObject(WHITE_BRUSH);
    ::SelectObject(hDCMem, hbrush);
    ::PatBlt(hDCMem, 0,0, ScreenMaxX, ScreenMaxY, PATCOPY );
    ::DeleteObject(hbrush);

    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Th, (LPVOID)hwnd, 0,&g_nMainThreadID);
    ShowWindow(hwnd, nShowCmd);
    UpdateWindow(hwnd);
    // Запускаем цикл обработки сообщений
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

Этот код медленно рисует две розовые полосы сверху вниз в разных потоках (потоку соответствует функция thread_func). Причём на Windows 7 полосы рисуются равномерно, а на Windows XP — с разной скоростью.

Я обнаружил, что если раскомментировать хотя бы одну из закомментированных строк с кодом, то поведение будет одинаковым. Но мне кажется, проблема не в этом. Почему всё-таки поведение программы различается?

READ ALSO
Как определить, есть ли буквы в строке? C++

Как определить, есть ли буквы в строке? C++

Как определить, есть ли буквы в строке без функций и очень коротко(буквы любые - и латинские, и русские)

566
Проблема с деструктором в С++

Проблема с деструктором в С++

Задача - создать класс stringЯ прописал конструкторы, перегрузил операции, и программа вроде работает нормально, но в последней строке возникает...

409
Можно ли использовать один сокет в нескольких потоках?

Можно ли использовать один сокет в нескольких потоках?

Клиентское приложение на C++ передаёт на HTTP-сервер данные - идентификатор клиента (чтобы обозначить присутствие), кадры с веб-камеры (по запросу),...

407
GNU C++ 4.8.4,перевод из int в char mass[]

GNU C++ 4.8.4,перевод из int в char mass[]

Имеется массив mass[] и число int qНеобходимо записать q по разрядам в массив

329