Visual Studio는 다중 스레드 애플리케이션을 디버그하는 데 도움이 되는 여러 도구 및 사용자 인터페이스 요소를 제공합니다. 이 자습서에서는 스레드 표식, 병렬 스택 창, 병렬 조사식 창, 조건부 중단점 및 필터 중단점을 사용하는 방법을 보여 줍니다. 이 자습서를 완료하면 다중 스레드 애플리케이션을 디버깅하기 위한 Visual Studio 기능을 숙지할 수 있습니다.
이 두 문서에서는 다른 다중 스레드 디버깅 도구를 사용하는 방법에 대한 추가 정보를 제공합니다.
디버그 위치 도구 모음 및 스레드 창을 사용하려면 연습: 다중 스레드 애플리케이션 디버그를 참조하세요.
(관리 코드) 및 동시성 런타임(C++)을 사용하는 Task 샘플은 연습: 병렬 애플리케이션 디버그를 참조하세요. 대부분의 다중 스레드 애플리케이션 유형에 적용되는 일반적인 디버깅 팁은 해당 문서와 이 문서를 모두 읽어보세요.
첫 번째 단계는 다중 스레드 애플리케이션 프로젝트를 만드는 것입니다.
다중 스레드 앱 프로젝트 만들기
Visual Studio를 열고 새 프로젝트를 만듭니다.
시작 창이 열려 있지 않으면 파일>시작 창선택합니다.
시작 창에서 새 프로젝트 만들기을 선택합니다.
새 프로젝트 만들기 창에서 검색 상자에 콘솔을 입력하거나 입력합니다. 다음으로 언어 목록에서 C#, C++또는 Visual Basic 을 선택한 다음 플랫폼 목록에서 Windows 를 선택합니다.
언어 및 플랫폼 필터를 적용한 후 .NET 또는 C++용 콘솔 앱 템플릿을 선택한 다음, 다음을 선택합니다.
비고
올바른 템플릿이 표시되지 않는 경우 도구>도구 및 기능 가져오기...로 이동하여 Visual Studio 설치 관리자를 엽니다. C++ 워크로드를 사용하여 .NET 데스크톱 개발 또는 데스크톱 개발을 선택한 다음 수정을 선택합니다.
새 프로젝트 구성 창의 프로젝트 이름 상자에 MyThreadWalkthroughApp을 입력하거나 입력합니다. 그런 다음, 사용할 수 있는 옵션 중 하나를 선택하여 다음 또는 만들기를 선택합니다.
.NET Core 또는 .NET 5+ 프로젝트의 경우 권장 대상 프레임워크 또는 .NET 8을 선택한 다음 만들기를 선택합니다.
새 콘솔 프로젝트가 나타납니다. 프로젝트를 만든 후 원본 파일이 나타납니다. 선택한 언어에 따라 원본 파일을 Program.cs, MyThreadWalkthroughApp.cpp 또는 Module1.vb 호출할 수 있습니다.
소스 파일에 표시되는 코드를 삭제하고 업데이트된 다음 코드로 바꿉니다. 코드 구성에 적합한 코드 조각을 선택합니다.
using System; using System.Threading; public class ServerClass { static int count = 0; // The method that will be called when the thread is started. public void InstanceMethod() { Console.WriteLine( "ServerClass.InstanceMethod is running on another thread."); int data = count++; // Pause for a moment to provide a delay to make // threads more apparent. Thread.Sleep(3000); Console.WriteLine( "The instance method called by the worker thread has ended. " + data); } } public class Simple { public static void Main() { for (int i = 0; i < 10; i++) { CreateThreads(); } } public static void CreateThreads() { ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); // Start the thread. InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread."); } }
파일 메뉴에서 모두 저장을 선택합니다.
(Visual Basic에만 해당) 솔루션 탐색기(오른쪽 창)에서 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 애플리케이션 탭에서 시작 개체를 Simple로 변경합니다.
다중 스레드 앱 디버그
소스 코드 편집기에서 다음 코드 조각을 찾습니다.
마우스 왼쪽 버튼을 클릭하여
Thread.Sleep
또는 C++std::this_thread::sleep_for
문장의 왼쪽 구역에 새 중단점을 삽입합니다.인터페이스의 가장자리에서 빨간색 원은 중단점이 이 위치에 설정되었음을 나타냅니다.
디버그 메뉴에서 디버깅 시작(F5)을 선택합니다.
Visual Studio는 솔루션을 빌드하고, 앱이 연결된 디버거를 사용하여 실행하기 시작한 다음, 앱이 중단점에서 중지됩니다.
소스 코드 편집기에서 중단점이 포함된 줄을 찾습니다.
스레드 마커 검색
디버그 도구 모음에서 소스에서 스레드 표시 버튼
를 선택합니다.
F11 키를 두 번 눌러 디버거를 진행합니다.
창의 왼쪽에 있는 배수로를 확인합니다. 이 줄에서는 두 개의 꼬인 실처럼 생긴 스레드 마커 아이콘
을 확인할 수 있습니다. 스레드 표식은 스레드가 이 위치에서 중지되었음을 나타냅니다.
스레드 마커는 중단점에 의해 부분적으로 숨겨질 수 있습니다.
포인터를 스레드 표식 위로 마우스로 가리킵니다. 중지된 각 스레드의 이름 및 스레드 ID 번호를 알려주는 DataTip이 나타납니다. 이 경우 이름은 다음과 같습니다
<noname>
.바로 가기 메뉴에서 사용 가능한 옵션을 보려면 스레드 표식을 선택합니다.
스레드 위치 보기
병렬 스택 창에서 스레드 보기와 (작업 기반 프로그래밍의 경우) 작업 보기 간에 전환할 수 있으며 각 스레드에 대한 호출 스택 정보를 볼 수 있습니다. 이 앱에서는 스레드 보기를 사용할 수 있습니다.
Windows>디버그>를 선택하여병렬 스택 창을 엽니다. 다음과 비슷한 내용이 표시됩니다. 정확한 정보는 각 스레드의 현재 위치, 하드웨어 및 프로그래밍 언어에 따라 달라질 수 있습니다.
이 예제에서는 왼쪽에서 오른쪽으로 관리 코드에 대한 다음 정보를 볼 수 있습니다.
- 현재 스레드(노란색 화살표)가 입력되었습니다
ServerClass.InstanceMethod
. 을 마우스로 가리키면 스레드의 스레드 ID 및 스택 프레임을 볼 수 있습니다ServerClass.InstanceMethod
. - 스레드 31724가 스레드 20272가 소유한 잠금을 기다리고 있습니다.
- [외부 코드]에서 주 스레드(왼쪽)가 중지되었습니다. 외부 코드 표시를 선택하면 자세히 볼 수 있습니다.
이 예제에서는 왼쪽에서 오른쪽으로 관리 코드에 대한 다음 정보를 볼 수 있습니다.
- 주 스레드(왼쪽)가 중지되었습니다
Thread.Start
. 여기서 중지점은 스레드 마커 아이콘로 식별됩니다.
- 두 개의 스레드가 들어갔
ServerClass.InstanceMethod
는데, 그 중 하나는 현재 스레드(노란색 화살표)이며 다른 스레드는 중지되었습니다Thread.Sleep
. - 오른쪽에 있는 새 스레드도 시작되지만 중지됩니다
ThreadHelper.ThreadStart
.
- 현재 스레드(노란색 화살표)가 입력되었습니다
목록 보기에서 스레드를 보려면Windows> 스레드 디버그>를 선택합니다.
이 보기에서는 스레드 20272가 주 스레드이며 현재 외부 코드, 특히 System.Console.dll있음을 쉽게 확인할 수 있습니다.
비고
스레드 창 사용에 대한 자세한 내용은 연습: 다중 스레드 애플리케이션 디버그를 참조하세요.
병렬 스택 또는 스레드 창에서 항목을 마우스 오른쪽 단추로 클릭하여 바로 가기 메뉴에서 사용 가능한 옵션을 확인합니다.
이러한 마우스 오른쪽 단추 클릭 메뉴에서 다양한 작업을 수행할 수 있습니다. 이 자습서에서는 병렬 조사식 창(다음 섹션)에서 이러한 세부 정보를 자세히 살펴봅니다.
변수에 조사식 설정
Windows>식 1 디버그>를 선택하여병렬 조사>식 창을 엽니다.
텍스트가 표시되는
<Add Watch>
셀(또는 네 번째 열의 빈 머리글 셀)을 선택하고 입력data
합니다.각 스레드의 데이터 변수 값이 창에 나타납니다.
텍스트가 표시되는
<Add Watch>
셀(또는 다섯 번째 열의 빈 머리글 셀)을 선택하고 입력count
합니다.각 스레드의
count
변수 값이 창에 표시됩니다. 아직 많은 정보가 표시되지 않으면 F11 키를 몇 번 눌러 디버거에서 스레드 실행을 진행합니다.창에서 행 중 하나를 마우스 오른쪽 단추로 클릭하여 사용 가능한 옵션을 확인합니다.
스레드 플래그 지정 및 플래그 해제
스레드에 플래그를 지정하여 중요한 스레드를 추적하고 다른 스레드를 무시할 수 있습니다.
병렬 조사식 창에서 Shift 키를 누른 채 여러 행을 선택합니다.
마우스 오른쪽 단추를 클릭하고 플래그를 선택합니다.
선택한 모든 스레드에 플래그가 지정됩니다. 이제 플래그가 지정된 스레드만 표시하도록 필터링할 수 있습니다.
병렬 관찰 창에서 플래그가 지정된 스레드만 표시 버튼
를 선택합니다.
플래그가 지정된 스레드만 목록에 표시됩니다.
팁 (조언)
일부 스레드에 플래그를 지정한 후 코드 편집기에서 코드 줄을 마우스 오른쪽 단추로 클릭하고 플래그가 지정된 스레드를 커서로 실행하도록 선택할 수 있습니다. 플래그가 지정된 모든 스레드가 도달할 코드를 선택해야 합니다. Visual Studio는 선택한 코드 줄에서 스레드를 일시 중지하므로 스레드를 동결 및 해동하여 실행 순서를 보다 쉽게 제어할 수 있습니다.
플래그가 지정된 스레드만 표시 단추를 다시 선택하여 모든 스레드 표시 모드로 다시 전환합니다.
스레드의 플래그를 해제하려면 병렬 조사식 창에서 하나 이상의 플래그가 지정된 스레드를 마우스 오른쪽 단추로 클릭하고 플래그 해제를 선택합니다.
스레드 실행 중지 및 해동
팁 (조언)
스레드가 작업을 수행하는 순서를 제어하기 위해 스레드를 동결 및 해동(일시 중단 및 다시 시작)할 수 있습니다. 이렇게 하면 교착 상태 및 경합 상태와 같은 동시성 문제를 해결하는 데 도움이 될 수 있습니다.
병렬 감시 창에서 모든 행이 선택된 상태에서 마우스 오른쪽 단추를 클릭하고 고정을 선택합니다.
두 번째 열에는 각 행에 대해 일시 중지 아이콘이 나타납니다. 일시 중지 아이콘은 스레드가 고정되었음을 나타냅니다.
한 행만 선택하여 다른 모든 행의 선택을 취소합니다.
행을 마우스 오른쪽 버튼으로 클릭하고 해제를 선택합니다.
스레드가 더 이상 고정되지 않음을 나타내는 일시 중지 아이콘이 이 행에서 사라집니다.
코드 편집기로 전환하고 F11 키를 누릅니다. 얼지 않은 스레드만 실행됩니다.
앱은 일부 새 스레드를 인스턴스화할 수도 있습니다. 모든 새 스레드는 플래그가 지정되지 않으며 고정 상태가 아닙니다.
조건부 중단점이 있는 단일 스레드 팔로우
디버거에서 단일 스레드의 실행을 따르는 것이 유용할 수 있습니다. 이렇게 하는 한 가지 방법은 관심 없는 스레드를 동결하는 것입니다. 일부 시나리오에서는 특정 버그를 재현하기 위해 다른 스레드를 동결하지 않고 단일 스레드를 따라야 할 수 있습니다. 다른 스레드를 동결하지 않고 스레드를 따르려면 관심 있는 스레드를 제외하고 코드에 침입하지 않아야 합니다. 조건부 중단점을 설정하여 이 작업을 수행할 수 있습니다.
스레드 이름 또는 스레드 ID와 같은 다양한 조건에서 중단점을 설정할 수 있습니다. 각 스레드에 고유한 것으로 알고 있는 데이터에 대한 조건을 설정하는 것이 유용할 수 있습니다. 이 방법은 특정 스레드보다 특정 데이터 값에 더 관심이 있을 때 디버깅하는 동안 일반적입니다.
이전에 만든 중단점을 마우스 오른쪽 단추로 클릭하고 조건을 선택합니다.
중단점 설정 창에서 조건식을 입력
data == 5
합니다.팁 (조언)
특정 스레드에 더 관심이 있는 경우 조건에 스레드 이름 또는 스레드 ID를 사용합니다. 중단점 설정 창에서 이 작업을 수행하려면 조건식 대신 필터를 선택하고 필터 팁을 따릅니다. 디버거를 다시 시작할 때 스레드 ID가 변경되므로 앱 코드에서 스레드 이름을 지정할 수 있습니다.
중단점 설정 창을 닫습니다.
단추를 선택하여 디버깅 세션을 다시 시작합니다.
데이터 변수의 값이 5인 스레드의 코드에 침입합니다. 병렬 조사식 창에서 현재 디버거 컨텍스트를 나타내는 노란색 화살표를 찾습니다.
이제 코드(F10)를 건너뛰고 코드(F11)로 들어가며 단일 스레드의 실행을 추적할 수 있습니다.
중단점 조건이 해당 스레드에만 고유하고 디버거가 다른 스레드의 중단점에 맞닥뜨리지 않는다면(다른 중단점을 사용하지 않도록 설정해야 할 수 있습니다), 다른 스레드로 전환할 필요 없이 코드를 단계 건너뛰기와 한 단계씩 실행하는 작업을 수행할 수 있습니다.
비고
디버거를 진행하면 모든 스레드가 실행됩니다. 그러나 다른 스레드 중 하나가 중단점에 도달하지 않는 한 디버거는 다른 스레드의 코드에 침입하지 않습니다.