티스토리 뷰

190703-3 플래그
 

교육을 받으면서 노트필기 했던 내용을 날것 그대로 업로드합니다.


 
플래그
#include <windows.h>
#include <TCHAR.H>
#include <vector>
using namespace std;
 
struct ThreadInfo {
    HANDLE hThread;
    bool bRun;
    HWND hwnd;
    POINT pt; // 클릭한 좌표
};
vector<ThreadInfo*> threadList; // 공유변수
 
#pragma region MyRegion
 
 
DWORD __stdcall DrawThread(LPVOID pParam);
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam);
 
HINSTANCE g_hInst;
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
    ...(생략)
}
#pragma endregion
 
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam)
{
    ThreadInfo* p;
    HANDLE hThread;
    static DWORD threadID;
    switch (iMsg)
    {
    case WM_CREATE:
 
        break;
    case WM_RBUTTONDOWN:
    {
 
    }
    break;
    case WM_LBUTTONDOWN:
    {
        p = new ThreadInfo;
        p->bRun = true;
        p->hwnd = hwnd;
        p->pt.x = LOWORD(lParam);
        p->pt.y = HIWORD(lParam);
        hThread = CreateThread(NULL, 0, DrawThread, p, 0, &threadID);
        ThreadInfo ti = { hThread,true };
        p->hThread = hThread;
        threadList.push_back(p);
    }
    break;
    
    case WM_DESTROY:
        PostQuitMessage(0);
        for (unsigned i = 0; i < threadList.size(); i++)
            CloseHandle(threadList[i]->hThread);
        break;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
int ThreadInfo2Index(const vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
 
    for (unsigned i = 0; i < threadList.size(); i++)
        if (threadList[i] == p) // 해당하는 인덱스를 찾았을 경우
            return i;
 
    return -1;
}
DWORD __stdcall DrawThread(LPVOID pParam) { // Worker 쓰레드 라고한다.
    Sleep(1000); // 공유 변수를 쓰게 되면 값을 늦게 가져와서 마우스 클릭이 더 빨랐을 경우 문제가 발생한다 (같은 좌표에 그림)
    ThreadInfo* p = (ThreadInfo*)pParam;
    HWND hwnd = p->hwnd;
    HDC hdc = GetDC(hwnd);
    POINT pt = p->pt;
    for (int count = 0; p->bRun && count < 5; count++)
    {
        for (int i = 0; i < 100; i += 5)
        {
            Rectangle(hdc, pt.x, pt.y, pt.x + i, pt.y + i);
            Sleep(40);
        }
    }
    ReleaseDC(hwnd, hdc);
 
    int delIndex = ThreadInfo2Index(threadList, p);
    threadList.erase(threadList.begin() + delIndex);
    delete p;
 
    return 0;
}
공유변수는 서로다른 쓰레드가 Write할 때 데이터가 더렵혀지는 현상이 발생한다. -> 동기화를 해야한다.
 
동기화는 따로 묶어논다. 동기화 작업만 함수로 묶어놓는다.
 
 
#include <windows.h>
#include <TCHAR.H>
#include <vector>
using namespace std;
 
struct ThreadInfo {
    HANDLE hThread;
    bool bRun;
    HWND hwnd;
    POINT pt; // 클릭한 좌표
};
vector<ThreadInfo*> threadList; // 공유변수
HANDLE hMutex;
#pragma region MyRegion
 
 
DWORD __stdcall DrawThread(LPVOID pParam);
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam);
 
HINSTANCE g_hInst;
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
    //(생략)
}
#pragma endregion
 
int ThreadInfo2Index(const vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    for (unsigned i = 0; i < threadList.size(); i++)
        if (threadList[i] == p) // 해당하는 인덱스를 찾았을 경우
            return i;
 
    return -1;
}
///////// Critical Section
void AddThreadInfo(vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    WaitForSingleObject(hMutex, INFINITE);
    threadList.push_back((ThreadInfo*)p); // 공유변수에 접근한다.
    ReleaseMutex(hMutex);
}
void RemoveThreadInfo(vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    WaitForSingleObject(hMutex, INFINITE);
    int delIndex = ThreadInfo2Index(threadList, p);
    threadList.erase(threadList.begin() + delIndex);// 인덱스 받아서 원소 제거
    ReleaseMutex(hMutex);
}
/////////
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam)
{
    ThreadInfo* p;
    HANDLE hThread;
    static DWORD threadID;
    switch (iMsg)
    {
    case WM_CREATE:
        hMutex = CreateMutex(NULL, FALSE, NULL);// 뮤텍스 생성
        break;
    case WM_RBUTTONDOWN:
    {
 
    }
    break;
    case WM_LBUTTONDOWN:
    {
        p = new ThreadInfo;
        p->bRun = true;
        p->hwnd = hwnd;
        p->pt.x = LOWORD(lParam);
        p->pt.y = HIWORD(lParam);
 
        hThread = CreateThread(NULL, 0, DrawThread, p, 0, &threadID);
        ThreadInfo ti = { hThread,true };
        p->hThread = hThread;
        AddThreadInfo(threadList, p);
    }
    break;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        for (unsigned i = 0; i < threadList.size(); i++)
            CloseHandle(threadList[i]->hThread);
        CloseHandle(hMutex);
        break;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
 
DWORD __stdcall DrawThread(LPVOID pParam) { // Worker 쓰레드 라고한다.
    ThreadInfo* p = (ThreadInfo*)pParam;
    HWND hwnd = p->hwnd;
    HDC hdc = GetDC(hwnd);
    POINT pt = p->pt;
    for (int count = 0; p->bRun && count < 5; count++)
    {
        for (int i = 0; i < 100; i += 5)
        {
            Rectangle(hdc, pt.x, pt.y, pt.x + i, pt.y + i);
            Sleep(40);
        }
    }
    ReleaseDC(hwnd, hdc);
 
    RemoveThreadInfo(threadList, p);
    delete p;
 
    return 0;
}
 
 
 
c++ 꿀Tip)
// 많이 쓰는 자원 관리 클래스
class ResMutex { // 리소스 뮤텍스
    HANDLE hMutex;
public:
    ResMutex(HANDLE hm):hMutex(hm) {
        WaitForSingleObject(hMutex, INFINITE);
    }
    ~ResMutex() {
        ReleaseMutex(hMutex);// 객체 생성시 소멸자 호출 보장하므로 ReleaseMutex() 보장
    }
};
클래스를 따로지정하여 생성자를 사용하여 뮤텍스를 생성한다.
///////// Critical Section
void AddThreadInfo(vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    ResMutex m(hMutex);
    threadList.push_back((ThreadInfo*)p); // 공유변수에 접근한다.
}
void RemoveThreadInfo(vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    ResMutex m(hMutex);
    int delIndex = ThreadInfo2Index(threadList, p);
    threadList.erase(threadList.begin() + delIndex);// 인덱스 받아서 원소 제거
}
/////////
장점 : 예외시 소멸자 호출이 보장된다.
 
플래그
#include <windows.h>
#include <TCHAR.H>
#include <vector>
using namespace std;
 
// 많이 쓰는 자원 관리 클래스
class ResMutex { // 리소스 뮤텍스
    HANDLE hMutex;
public:
    ResMutex(HANDLE hm) :hMutex(hm) {
        WaitForSingleObject(hMutex, INFINITE);
    }
    ~ResMutex() {
        ReleaseMutex(hMutex);
    }
};
 
struct ThreadInfo {
    HANDLE hThread;
    bool bRun;
    HWND hwnd;
    POINT pt; // 클릭한 좌표
};
vector<ThreadInfo*> threadList; // 공유변수
HANDLE hMutex;
 
void RemoveRandThreadInfo(vector<ThreadInfo*>& threadList) {
    ResMutex m(hMutex); // 동기화 작업을한다. 임계영역을 설정
    int exitIndex = rand() % threadList.size();
    threadList[exitIndex]->bRun=false;
}
#pragma region MyRegion
 
 
DWORD __stdcall DrawThread(LPVOID pParam);
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam);
 
HINSTANCE g_hInst;
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
    생략
}
#pragma endregion
 
int ThreadInfo2Index(const vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    for (unsigned i = 0; i < threadList.size(); i++)
        if (threadList[i] == p) // 해당하는 인덱스를 찾았을 경우
            return i;
 
    return -1;
}
///////// Critical Section
void AddThreadInfo(vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    ResMutex m(hMutex);
    threadList.push_back((ThreadInfo*)p); // 공유변수에 접근한다.
}
void RemoveThreadInfo(vector<ThreadInfo*>& threadList, const ThreadInfo* p) {
    ResMutex m(hMutex);
    int delIndex = ThreadInfo2Index(threadList, p);
    threadList.erase(threadList.begin() + delIndex);// 인덱스 받아서 원소 제거
}
/////////
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam)
{
    ThreadInfo* p;
    HANDLE hThread;
    static DWORD threadID;
    switch (iMsg)
    {
    case WM_CREATE:
        hMutex = CreateMutex(NULL, FALSE, NULL);// 뮤텍스 생성
        break;
    case WM_RBUTTONDOWN:
    {
        RemoveRandThreadInfo(threadList);
    }
    break;
    case WM_LBUTTONDOWN:
    {
        p = new ThreadInfo;
        p->bRun = true;
        p->hwnd = hwnd;
        p->pt.x = LOWORD(lParam);
        p->pt.y = HIWORD(lParam);
 
        hThread = CreateThread(NULL, 0, DrawThread, p, 0, &threadID);
        ThreadInfo ti = { hThread,true };
        p->hThread = hThread;
        AddThreadInfo(threadList, p);
    }
    break;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        for (unsigned i = 0; i < threadList.size(); i++)
            CloseHandle(threadList[i]->hThread);
        CloseHandle(hMutex);
        break;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
 
DWORD __stdcall DrawThread(LPVOID pParam) { // Worker 쓰레드 라고한다.
    ThreadInfo* p = (ThreadInfo*)pParam;
    HWND hwnd = p->hwnd;
    HDC hdc = GetDC(hwnd);
    POINT pt = p->pt;
    for (int count = 0; p->bRun && count < 5; count++)
    {
        for (int i = 0; i < 100; i += 5)
        {
            Rectangle(hdc, pt.x, pt.y, pt.x + i, pt.y + i);
            Sleep(40);
        }
    }
    ReleaseDC(hwnd, hdc);
 
    RemoveThreadInfo(threadList, p);
    delete p;
 
    return 0;
}
리스트의 사이즈를 가져와서 랜덤으로 제거하는데 그 연산을 임계영역으로 지정하여 수행한다.
 
#include <windows.h>
#include <TCHAR.H>
 
struct TP {
    LPTSTR str; //== THAR*
    int x;
    int y;
};
 
HWND gHwnd;
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
   생략
}
 
//Thread Function
DWORD __stdcall TF(LPVOID param) {
    const TP* tp = (const TP*)param;
    HDC dc = GetDC(gHwnd);
    TextOut(dc, tp->x, tp->y, tp->str, lstrlen(tp->str));
    ReleaseDC(gHwnd, dc);
 
    delete tp; // 동적으로 할당받은 heap메모리를 해제한다.
    return 0;
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam)
{
    HANDLE hThread;
    DWORD id;
    TP* p;
    switch (iMsg)
    {
    case WM_CREATE:
        gHwnd = hwnd;
        break;
    case WM_LBUTTONDOWN:
        p = new TP();//쓰레드 파라미터를 힙메모리에 생성후
        p->str = (LPTSTR)_T("Hello!");
        p->x = LOWORD(lParam);
        p->y = HIWORD(lParam);
 
        hThread = CreateThread(NULL, 0, TF, p, 0, &id);//p로 전달해서 사용한다.
        CloseHandle(hThread);// 핸들을 사용하지 않을거라 핸들반환
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
댓글
댓글쓰기 폼
네이버 이웃추가
«   2019/10   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
글 보관함