다중 스레딩: MFC 프로그래밍 팁
다중 스레드 애플리케이션은 작업이 의도한 순서대로 수행되고 여러 스레드에서 액세스하는 모든 데이터가 손상되지 않도록 하기 위해 단일 스레드 애플리케이션보다 더 엄격한 주의가 필요합니다. 이 항목에서는 MFC(Microsoft Foundation Class) 라이브러리를 사용하여 다중 스레드 애플리케이션을 프로그래밍할 때 잠재적인 문제를 방지하는 기술에 대해 설명합니다.
여러 스레드에서 개체 액세스
MFC 개체는 스레드로부터 안전하지 않습니다. MFC 동기화 클래스 및/또는 중요한 섹션과 같은 적절한 Win32 동기화 개체를 사용하지 않는 한 두 개의 별도 스레드가 동일한 개체를 조작할 수 없습니다. 중요한 섹션 및 기타 관련 개체에 대한 자세한 내용은 Windows SDK의 동기화를 참조하세요.
클래스 라이브러리는 내부적으로 중요한 섹션을 사용하여 디버그 메모리 할당에 사용되는 것과 같은 전역 데이터 구조를 보호합니다.
MFC가 아닌 스레드에서 MFC 개체 액세스
CWinThread 개체를 사용하지 않는 방식으로 스레드를 만드는 다중 스레드 애플리케이션이 있는 경우 해당 스레드에서 다른 MFC 개체에 액세스할 수 없습니다. 즉, 보조 스레드에서 MFC 개체에 액세스하려는 경우 다중 스레딩에 설명된 방법 중 하나인 사용자 인터페이스 스레드 만들기 또는 다중 스레딩: 작업자 스레드 만들기 중 하나를 사용하여 해당 스레드를 만들어야 합니다. 이러한 메서드는 클래스 라이브러리가 다중 스레드 애플리케이션을 처리하는 데 필요한 내부 변수를 초기화할 수 있는 유일한 메서드입니다.
Windows 핸들 지도
일반적으로 스레드는 만든 MFC 개체에만 액세스할 수 있습니다. 이는 임시 및 영구 Windows 핸들 맵이 스레드 로컬 스토리지에 보관되어 기본 여러 스레드의 동시 액세스로부터 보호를 받기 때문입니다. 예를 들어 작업자 스레드는 계산을 수행한 다음 문서의 UpdateAllViews
멤버 함수를 호출하여 새 데이터에 대한 뷰가 포함된 창을 수정할 수 없습니다. 개체에서 CWnd
HWND로의 맵이 기본 스레드에 로컬이기 때문에 전혀 효과가 없습니다. 즉, 한 스레드가 Windows 핸들에서 C++ 개체로 매핑될 수 있지만 다른 스레드는 동일한 핸들을 다른 C++ 개체에 매핑할 수 있습니다. 한 스레드에서 변경된 내용은 다른 스레드에 반영되지 않습니다.
이 문제에는 여러 가지 방법이 있습니다. 첫 번째는 C++ 개체가 아닌 개별 핸들(예: HWND)을 작업자 스레드에 전달하는 것입니다. 그런 다음 작업자 스레드는 적절한 FromHandle
멤버 함수를 호출하여 이러한 개체를 임시 맵에 추가합니다. 호출하여 스레드의 영구 맵에 Attach
개체를 추가할 수도 있지만 개체가 스레드보다 더 오래 존재하도록 보장되는 경우에만 이 작업을 수행해야 합니다.
또 다른 방법은 작업자 스레드가 수행할 다양한 작업에 해당하는 새 사용자 정의 메시지를 만들고 이러한 메시지를 사용하여 ::PostMessage
애플리케이션의 기본 창에 게시하는 것입니다. 이 통신 방법은 두 스레드가 동일한 주소 공간에서 실행되고 있다는 점을 제외하고는 서로 다른 두 애플리케이션이 대화하는 것과 유사합니다.
핸들 맵에 대한 자세한 내용은 Technical Note 3을 참조하세요. 스레드 로컬 스토리지에 대한 자세한 내용은 Windows SDK에서 스레드 로컬 스토리지 및 스레드 로컬 스토리지 사용을 참조하세요.
스레드 간 통신
MFC는 스레드가 개체에 대한 액세스를 동기화하여 스레드 보안을 기본 수 있는 여러 클래스를 제공합니다. 이러한 클래스의 사용법은 다중 스레딩: 동기화 클래스 및 다중 스레딩을 사용하는 방법: 동기화 클래스를 사용하는 경우에 설명되어 있습니다. 이러한 개체에 대한 자세한 내용은 Windows SDK의 동기화를 참조하세요.