590 likes | 1.06k Views
Visual C++ Programming Tree Control/MultiThread. Department of Digital Contents Sang Il Park. Tree Control. 트리 컨트롤 (1/2). 트리 컨트롤 = 트리 뷰 컨트롤 이미지와 텍스트를 이용하여 계층적인 형태로 정보를 표시하는 용도로 사용. 트리 컨트롤 (2/2). 용어 항목 트리 컨트롤에 표시되는 하나의 정보 부모 항목 하나 이상의 하위 항목을 가진 항목 자식 항목 부모 항목에 딸린 하위 항목 루트 항목
E N D
Visual C++ ProgrammingTree Control/MultiThread Department of Digital Contents Sang Il Park
트리 컨트롤 (1/2) • 트리 컨트롤 = 트리 뷰 컨트롤 • 이미지와 텍스트를 이용하여 계층적인 형태로 정보를 표시하는 용도로 사용
트리 컨트롤 (2/2) • 용어 • 항목 • 트리 컨트롤에 표시되는 하나의 정보 • 부모 항목 • 하나 이상의 하위 항목을 가진 항목 • 자식 항목 • 부모 항목에 딸린 하위 항목 • 루트 항목 • 계층 구조에서 최상위 항목 • 루트 항목은 부모 항목을 가지지 않음
트리 컨트롤 클래스 (1/11) • 트리 컨트롤 생성과 초기화 • CTreeCtrl 객체 선언 후 CTreeCtrl::Create()로 트리 컨트롤 생성 • CImageList 객체 선언 후 CImageList::Create(), CImageList::Add() 등을 이용하여 생성과 초기화 • CTreeCtrl::SetImageList()로 트리 컨트롤에서 사용할 이미지 리스트 설정 • CTreeCtrl::InsertItem()으로 항목 추가
트리 컨트롤 클래스 (2/11) • 예제 코드 // ① CTreeCtrl 객체 선언과 트리 컨트롤 생성 m_tree.Create(WS_CHILD|WS_VISIBLE|WS_BORDER| TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT, CRect(10, 10, 150, 150), this, 101); // ② CImageList 객체 선언과 이미지 리스트 생성, 초기화 CImageList il; il.Create(IDB_BITMAP1, 16, 1, RGB(255, 255, 255));
트리 컨트롤 클래스 (3/11) • 예제 코드 (cont'd) // ③ 이미지 리스트 설정 m_tree.SetImageList(&il, TVSIL_NORMAL); il.Detach(); // ④ 항목 추가 // 1레벨 초기화 HTREEITEM hSun = m_tree.InsertItem("태양", 0, 0, TVI_ROOT, TVI_LAST);
트리 컨트롤 클래스 (4/11) • 예제 코드 (cont'd) // 2레벨 초기화 m_tree.InsertItem("수성", 1, 1, hSun, TVI_LAST); m_tree.InsertItem("금성", 1, 1, hSun, TVI_LAST); HTREEITEM hEarth = m_tree.InsertItem("지구", 1, 1, hSun, TVI_LAST); HTREEITEM hMars = m_tree.InsertItem("화성", 1, 1, hSun, TVI_LAST); // 3레벨 초기화 m_tree.InsertItem("달", 2, 2, hEarth, TVI_LAST); m_tree.InsertItem("포보스", 2, 2, hMars, TVI_LAST); m_tree.InsertItem("데이모스", 2, 2, hMars, TVI_LAST);
트리 컨트롤 클래스 (7/11) • 주요 함수 (cont'd) • lpszItem: 항목에 표시할 텍스트 • nImage: 항목에 표시할 이미지를 나타내며 이미지 리스트에서의 인덱스 값을 사용 • nSelectedImage: 항목이 선택되면 표시할 이미지를 나타내며 이미지 리스트에서의 인덱스 값을 사용 HTREEITEM CTreeCtrl::InsertItem (LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);
트리 컨트롤 클래스 (8/11) • 주요 함수 (cont'd) • hParent: 부모 항목을 나타내는 HTREEITEM 값이다. 루트 항목을 추가할 경우에는 TVI_ROOT를 사용 • hInsertAfter: 항목을 추가할 위치를 나타내며 보통 다음 표의 값 중 하나를 사용. 항목 다음 위치에 추가하고 싶을 경우 그 항목을 나타내는 HTREEITEM 값을 사용
트리 컨트롤 클래스 (9/11) • 스타일 변경하기 • dwRemove: 제거할 스타일 • dwAdd: 추가할 스타일 • nFlags: 기본값 사용 BOOL CWnd::ModifyStyle (DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);
트리 컨트롤 클래스 (10/11) • 선택 항목 알아내기 HTREEITEM hItem = m_tree.GetSelectedItem(); if(hItem != NULL) { CString str = m_tree.GetItemText(hItem); MessageBox(str); }
트리 컨트롤 클래스 (11/11) • 항목 추가와 삭제 • 항목 추가 • CTreeCtrl::InsertItem() • 항목 삭제 • CTreeCtrl::DeleteItem() HTREEITEM hItem = m_tree.GetSelectedItem(); if(hItem != NULL) { m_tree.DeleteItem(hItem); }
기타 공통 콘트롤 • 프로그레스 컨트롤 • 오랜 시간이 걸리는 작업의 진행 상황을 시각적으로 표시하는 용도로 사용
프로그레스 컨트롤 클래스 • 범위 설정와 현재 범위 얻기 • 위치 설정과 현재 위치 얻기 • 위치값 증감 void CProgressCtrl::SetRange (short nLower, short nUpper); void CProgressCtrl::GetRange (int& nLower, int& nUpper); int CProgressCtrl::SetPos (int nPos); int CProgressCtrl::GetPos (); int CProgressCtrl::OffsetPos (int nPos); int CProgressCtrl::SetStep (int nStep); int CProgressCtrl::StepIt ();
Announcement • 기말고사 • 6월 16일 화요일 • 수업시간/수업장소 • 문제유형: 중간고사와 동일 • 숙제/교재 예제에서도 출제 • Open Book/No Network
개요 • 멀티태스킹과 멀티스레딩 • 멀티태스킹 • 하나의 CPU가 여러 개의 프로세스를 교대로 수행 • 멀티스레딩 • 하나의 CPU가 여러 개의 스레드를 교대로 수행 • 멀티스레딩의 중요성 • 응용 프로그램이 직접 스레드 생성과 파괴를 관리 • 스레드 사용 여부에 따라 응용 프로그램의 성능 차이가 생기므로 중요한 프로그래밍 요소임
프로세스와 스레드 (1/4) • 프로세스 • 실행 중인 프로그램 • 프로세스 구성 요소 • 가상 주소 공간 - 32비트 윈도우의 경우 4기가 바이트 • 가상 주소 공간에 로드된 실행 파일과 DLL(코드+리소스+데이터) • 프로세스를 위해 운영체제가 할당한 각종 리소스(파일, 파이프, ...) • 프로세스 커널 객체 • 하나 이상의 스레드
프로세스의 가상 주소 공간 윈도우 운영체제 코드, 리소스, 데이터 프로세스 커널 객체 파일, 파이프, ... 스레드 1 스레드 2 프로세스와 스레드 (2/4) • 프로세스 구성 요소 (cont'd)
프로세스와 스레드 (3/4) • 스레드 • 프로세스의 가상 주소 공간에 존재하는 실행 흐름 • 운영 체제는 각 스레드에게 일정한 CPU 시간을 교대로 할당함으로써 여러 개의 스레드가 병렬적으로 실행되는 효과를 만들어 냄 • 스레드 구성 요소 • 스택 • 커널 모드와 사용자 모드에서 실행하기 위한 두 개의 스택 • 스레드 커널 객체 • CPU 레지스터 값, ...
프로세스의 가상 주소 공간 윈도우 운영체제 코드, 리소스, 전역 데이터 프로세스 커널 객체 힙(Heap) 스레드 커널 객체 환경 변수 스레드 커널 객체 스택 (스레드 1) 스택 (스레드 2) ... 프로세스와 스레드 (4/4) • 프로세스와 스레드 구성 요소
CPU 스케줄링 (1/5) • CPU 스케줄링 • 한정된 CPU 시간을 여러 스레드(혹은 프로세스)로 분배하는 정책 • 윈도우의 CPU 스케줄링 • 우선순위(Priority)에 기반한 CPU 스케줄링 기법을 사용 • 우선순위가 높은 스레드에게 우선적으로 CPU 시간 할당 • 스레드의 우선순위 결정 요소 • 프로세스 우선순위: 우선순위 클래스(Priority Class) • 스레드 우선순위: 우선순위 레벨(Priority Level)
CPU 스케줄링 (2/5) • 우선순위 클래스 • 프로세스 속성 • 하나의 프로세스가 생성한 스레드는 모두 동일한 우선순위 클래스를 가짐 • 우선순위 클래스 종류 REALTIME_PRIORITY_CLASS(실시간) HIGH_PRIORITY_CLASS(높음) ABOVE_NORMAL_PRIORITY_CLASS(보통 초과; 윈도우2000/XP) NORMAL_PRIORITY_CLASS(보통) BELOW_NORMAL_PRIORITY_CLASS(보통 미만; 윈도우2000/XP) IDLE_PRIORITY_CLASS(낮음)
CPU 스케줄링 (3/5) • 우선순위 클래스 종류 (cont'd)
CPU 스케줄링 (4/5) • 우선순위 레벨 • 스레드 속성 • 같은 프로세스에 속한 스레드 사이에서 상대적인 우선순위를 결정할 때 사용 • 우선순위 레벨 종류 THREAD_PRIORITY_TIME_CRITICAL THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_LOWEST THREAD_PRIORITY_IDLE
(낮음) 기초 우선순위 (높음) ... 스케줄러 스레드 CPU CPU 스케줄링 (5/5) • 우선순위 클래스 + 우선순위 레벨 기초 우선순위(Base Priority)
공유 변수 int money 스레드 1 스레드 2 ... ① read money ② money = money+1000 ③ write money ... ... ① read money ② money = money+2000 ③ write money ... 스레드 동기화 (1/2) • 스레드 동기화가 필요한 상황
스레드 동기화 (2/2) • 동기화 문제는 MFC 라이브러리 사이에서도 발생될 수 있다. 적절한 C/C++ 라이브러리 선택
MFC 스레드 • MFC 스레드 종류 • 작업자 스레드 • 메시지 루프를 가지고 있지 않다. • 사용자 인터페이스 스레드(UI 스레드) • 메시지 루프를 가지고 있다.
작업자 스레드 사용하기: UINT: Unsigned Integer LPVOID: 32bit 크기를 가지는 임의의 변수형 (ex. 정수, pointer) • 1. 작업을 수행할 전역함수 선언 • 2. 전역함수를 AfxBeginThread를 통해 호출 UINT DoIt( LPVOID value ) { … } AfxBeginThread(DoIt, (LPVOID) value);
작업자 스레드 (1/5) • 스레드 생성 CWinThread 타입 객체를 동적으로 생성하고 (스레드 를 만든 후) 이 객체의 주소값을 리턴 CWinThread* AfxBeginThread ( AFX_THREADPROC pfnThreadProc, // 함수이름 LPVOID pParam, // 전달할 파라메터 int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
작업자 스레드 (2/5) CWinThread* AfxBeginThread ( pfnThreadProc, pParam, nPriority, nStackSize, dwCreateFlags, lpSecurityAttrs ); • 스레드 생성 (cont'd) • pfnThreadProc: 스레드 실행 시작점이 되는 함수(=제어 함수)의 주소 • 제어 함수의 형태 UINT 함수이름 (LPVOID pParam); • pParam: 제어 함수에 전달할 인자(32비트) • nPriority: 스레드의 우선순위 레벨 • nStackSize: 스레드 스택의 크기 • dwCreateFlags: 0 또는 CREATE_SUSPENDED • lpSecurityAttrs: 보안 설명자와 핸들 상속 정보
작업자 스레드 (3/5) • 스레드 제어 • 스레드 우선순위 레벨 값을 얻음 • 스레드 우선순위 레벨 값을 변경 • 스레드 실행을 일시 정지 • 스레드를 재시작 int CWinThread::GetThreadPriority (); BOOL CWinThread::SetThreadPriority (int nPriority); DWORD CWinThread::SuspendThread (); DWORD CWinThread::ResumeThread ();
작업자 스레드 (4/5) • 스레드 종료 • 방법 1: 스레드 제어 함수가 리턴. 리턴값이 0이면 일반적으로 정상 종료를 뜻함 • 방법 2: 스레드 제어 함수 내에서 AfxEndThread() 호출
작업자 스레드 (5/5) • 스레드 종료 (cont'd) • nExitCode: 스레드 종료 코드 • bDelete: 스레드 객체를 메모리에서 제거할 것인지를 나타냄. FALSE를 사용하면 스레드 객체 재사용 가능 void AFXAPI AfxEndThread( UINT nExitCode, BOOL bDelete = TRUE );
코딩연습 • 다음과 같은 대화상자 기반 프로그램을 만들고 버튼을 만들면 1부터 200까지 더한 수를 계산하는 프로그램을 Thread를 이용하여 만들라.
코딩연습 • 왼쪽 마우스를 클릭하면 왼쪽에서 오른쪽으로 빨간 막대를 증가시키는 프로그램을 만들어라.
코딩연습 • 같은 프로그램을 Progress Bar를 붙여서 진행도를 표시하라 Progress Control주요 맴버 함수: SetRange (min, max) SetPos (value)
스레드 동기화 (1/3) • MFC 클래스 계층도
스레드 동기화 (2/3) • 클래스 요약 : • CSyncObject • 스레드 동기화 클래스를 위한 공통의 인터페이스 제공 • CCriticalSection, CEvent, CMutex, CSemaphore • 윈도우 운영체제에서 제공하는 스레드 동기화 객체(임계 영역, 이벤트, 뮤텍스, 세마포)를 편리하고 일관성 있게 사용할 수 있도록 만든 클래스 • CSingleLock, CMultiLock • 스레드 동기화 클래스를 편리하게 사용할 수 있도록 보조 사용하기 위해서는 afxmt.h에 가 필요
매개체 스레드 1 스레드 2 진행 대기 스레드 동기화 (3/3) • 스레드 동기화가 필요한 상황 • 두 개 이상의 스레드가 공유 리소스를 사용하는 경우 • 하나의 스레드가 작업을 완료한 후, 기다리고 있던 다른 모든 스레드에게 알려주는 경우 • 스레드 동기화 원리
Critical Section(1/2) • 용도 • 같은 프로세스에 속한 스레드 간의 동기화 • 공유 리소스를 접근하는 다수의 스레드가 있을 때 오직 하나의 스레드만 접근할 수 있도록 함 • 장점 • 속도가 빠름 • 단점 • 서로 다른 프로세스에 속한 스레드 간의 동기화를 위한 목적으로는 사용할 수 없음
Critical Section(2/2) • 사용 예 // 전역 변수로 선언 CCriticalSection g_cs; ... // 스레드 1 g_cs.Lock(); // 공유 변수 접근 g_cs.Unlock(); ... // 스레드 2 g_cs.Lock(); // 공유 변수 접근 g_cs.Unlock();
Mutex(1/3) • 용도 • 공유 리소스를 접근하는 다수의 스레드가 있을 때 오직 하나의 스레드만 접근할 수 있도록 함 • 장점 • 서로 다른 프로세스에 속한 스레드 간의 동기화를 위한 목적으로는 사용할 수 있음 • 단점 • 임계 영역보다 속도가 느림
Mutex(2/3) • 뮤텍스 생성 • bInitiallyOwn: TRUE면 뮤텍스를 생성한 스레드가 소유자가 됨 • lpszName: 뮤텍스 이름 • lpsaAttribute: 보안 설명자와 핸들 상속 관련 구조체 CMutex::CMutex ( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
Mutex(3/3) • 사용 예 // 전역 변수로 선언 CMutex g_mutex(FALSE, NULL); ... // 스레드 1 g_cs.Lock(); // 공유 변수 접근 g_cs.Unlock(); ... // 스레드 2 g_cs.Lock(); // 공유 변수 접근 g_cs.Unlock();
Event(1/5) • 이벤트 • 신호(Signaled)와 비신호(Nonsignaled) 두 개의 상태를 가진 동기화 객체 • 용도 • 두 개 이상의 스레드가 공유 리소스를 사용하는 경우 임계 영역, 뮤텍스, 이벤트(자동 리셋) • 하나의 스레드가 작업을 완료한 후, 기다리고 있던 다른 모든 스레드에게 알려주는 경우 이벤트(수동 리셋)
Event(2/5) • 이벤트 객체를 이용한 동기화 • 이벤트 객체를 비신호 상태로 생성 • 하나의 스레드가 초기화 작업을 진행하고, 나머지 스레드는 이벤트 객체에 대해 Lock()을 호출함으로써 이벤트 객체가 신호 상태가 되기를 기다림 • 스레드가 초기화 작업을 완료하면 이벤트 객체를 신호 상태로 바꿈 • 기다리고 있던 모든 스레드가 깨어나서 작업을 진행
Event(3/5) • 종류 • 자동 리셋(Auto Reset) • 이벤트 객체를 신호 상태로 바꾸면, 기다리는 스레드 중 하나만 깨운 후 자동으로 비신호 상태가 됨 • 수동 리셋(Manual Reset) • 이벤트 객체를 신호 상태로 바꾸면, 계속 신호 상태를 유지. 결과적으로 기다리는 스레드를 모두 깨우게 됨. • 리셋을 하려면 명시적으로 함수를 호출해야 함