Skip to content

Commit 82771df

Browse files
committed
multithreaded content updates
1 parent d903405 commit 82771df

File tree

1 file changed

+353
-0
lines changed

1 file changed

+353
-0
lines changed
Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
---
2+
title: "Get started debugging multithreaded applications | Microsoft Docs"
3+
ms.custom: ""
4+
ms.date: "04/18/2017"
5+
ms.reviewer: ""
6+
ms.suite: ""
7+
ms.technology:
8+
- "vs-ide-debug"
9+
ms.tgt_pltfrm: ""
10+
ms.topic: "article"
11+
dev_langs:
12+
- "CSharp"
13+
- "VB"
14+
- "FSharp"
15+
- "C++"
16+
helpviewer_keywords:
17+
- "multithreaded debugging, tutorial"
18+
- "tutorials, multithreaded debugging"
19+
ms.assetid: 62df746b-b0f6-4df4-83cf-b1d9d2e72833
20+
caps.latest.revision: 38
21+
author: "mikejo5000"
22+
ms.author: "mikejo"
23+
manager: "ghogen"
24+
translation.priority.ht:
25+
- "cs-cz"
26+
- "de-de"
27+
- "es-es"
28+
- "fr-fr"
29+
- "it-it"
30+
- "ja-jp"
31+
- "ko-kr"
32+
- "pl-pl"
33+
- "pt-br"
34+
- "ru-ru"
35+
- "tr-tr"
36+
- "zh-cn"
37+
- "zh-tw"
38+
---
39+
# Get started debugging a multithreaded application in Visual Studio
40+
Visual Studio provides a many tools and other user interface elements to help you debug multithreaded applications. This tutorial shows how to use conditional breakpoints, the **Parallel Stacks** window, and **Parallel Watch** window. This tutorial takes only a few minutes, but completing it will familiarize you with the features for debugging multithreaded applications.
41+
42+
Other topics provide additional information on using other multithreaded debugging tools:
43+
44+
- For a similar topic with a sample that uses <xref:System.Threading.Tasks.Task> or the concurrency runtime, see [Walkthrough: Debugging a Parallel Application](../debugger/walkthrough-debugging-a-parallel-application.md). Many of the concepts and tips in this topic will also apply to debugging parallel applications.
45+
46+
- To learn how to use the **Debug Location** toolbar and the **Threads** window, see [Walkthrough: Debug a Multithreaded Application](../debugger/how-to-use-the-threads-window.md).
47+
48+
To begin this tutorial, you need a multithreaded application project. Follow the steps listed here to create that project.
49+
50+
#### To create the multithreaded app project
51+
52+
1. On the **File** menu, choose **New** and then click **Project**.
53+
54+
The **New Project** dialog box appears.
55+
56+
2. In the **Project Type**s box, click the language of your choice: **Visual C#** or **Visual C++**.
57+
58+
3. In the **Templates** box, choose **Console App**.
59+
60+
4. In the **Name** box, type the name MyThreadWalkthroughApp.
61+
62+
5. Click **OK**.
63+
64+
A new console project appears. When the project has been created, a source file appears. Depending on the language you have chosen, the source file might be called Program.cs, or MyThreadWalkthroughApp.cpp
65+
66+
6. Delete the code that appears in the source file and replace it with the example code shown here (this is modified code from the "Creating a Thread" section of the topic [Creating Threads and Passing Data at Start Time](/dotnet/articles/standard/threading/creating-threads-and-passing-data-at-start-time).
67+
68+
```C#
69+
using System;
70+
using System.Threading;
71+
72+
public class ServerClass
73+
{
74+
75+
static int count = 0;
76+
// The method that will be called when the thread is started.
77+
public void InstanceMethod()
78+
{
79+
Console.WriteLine(
80+
"ServerClass.InstanceMethod is running on another thread.");
81+
82+
int data = count++;
83+
// Pause for a moment to provide a delay to make
84+
// threads more apparent.
85+
Thread.Sleep(3000);
86+
Console.WriteLine(
87+
"The instance method called by the worker thread has ended.");
88+
}
89+
}
90+
91+
public class Simple
92+
{
93+
public static void Main()
94+
{
95+
for (int i = 0; i < 10; i++)
96+
{
97+
CreateThreads();
98+
}
99+
}
100+
public static void CreateThreads()
101+
{
102+
ServerClass serverObject = new ServerClass();
103+
104+
Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod));
105+
// Start the thread.
106+
InstanceCaller.Start();
107+
108+
Console.WriteLine("The Main() thread calls this after "
109+
+ "starting the new InstanceCaller thread.");
110+
111+
}
112+
}
113+
```
114+
115+
```C++
116+
using namespace System;
117+
using namespace System::Threading;
118+
119+
public ref class ServerClass
120+
{
121+
public:
122+
123+
static int count = 0;
124+
125+
// The method that will be called when the thread is started.
126+
void InstanceMethod()
127+
{
128+
Console::WriteLine(
129+
"ServerClass.InstanceMethod is running on another thread.");
130+
131+
int data = count++;
132+
// Pause for a moment to provide a delay to make
133+
// threads more apparent.
134+
Thread::Sleep(3000);
135+
Console::WriteLine(
136+
"The instance method called by the worker thread has ended.");
137+
}
138+
};
139+
140+
public ref class Simple
141+
{
142+
public:
143+
static void Main()
144+
{
145+
for (size_t i = 0; i < 10; i++)
146+
{
147+
CreateThreads();
148+
}
149+
}
150+
151+
static void CreateThreads()
152+
{
153+
ServerClass^ serverObject = gcnew ServerClass();
154+
155+
// Create the thread object, passing in the
156+
// serverObject.InstanceMethod method using a
157+
// ThreadStart delegate.
158+
Thread^ InstanceCaller = gcnew Thread(
159+
gcnew ThreadStart(serverObject, &ServerClass::InstanceMethod));
160+
161+
// Start the thread.
162+
InstanceCaller->Start();
163+
164+
Console::WriteLine("The Main() thread calls this after "
165+
+ "starting the new InstanceCaller thread.");
166+
}
167+
};
168+
169+
int main()
170+
{
171+
Simple::Main();
172+
}
173+
```
174+
175+
7. On the **File** menu, click **Save All**.
176+
177+
#### To begin the tutorial
178+
179+
- In the source code editor, look for the following code:
180+
181+
```CSharp
182+
Thread.Sleep(3000);
183+
Console.WriteLine();
184+
```
185+
186+
```C++
187+
Thread::Sleep(3000);
188+
Console.WriteLine();
189+
```
190+
191+
#### To start debugging
192+
193+
1. Click in the left gutter of the `Thread.Sleep` or `Thread::Sleep` statement to insert a new breakpoint.
194+
195+
In the gutter on the left side of the source code editor, a red ball appears. This indicates that a breakpoint is now set at this location.
196+
197+
2. (C++ Console app) Build the solution (**Build / Build Solution**).
198+
199+
3. On the **Debug** menu, click **Start Debugging** (**F5**).
200+
201+
Debugging starts, your console application starts to run, and then stops at the breakpoint.
202+
203+
4. If the console application window has focus at this point, click in the [!INCLUDE[vsprvs](../code-quality/includes/vsprvs_md.md)] window to return focus to [!INCLUDE[vsprvs](../code-quality/includes/vsprvs_md.md)].
204+
205+
5. In the source code editor, locate the line that contains the following code:
206+
207+
```CSharp
208+
Thread.Sleep(3000);
209+
```
210+
211+
```C++
212+
Thread::Sleep(3000);
213+
```
214+
215+
#### To discover the thread marker
216+
217+
1. In the Debug Toolbar, click the **Show Threads in Source** button ![Show Threads in Source](../debugger/media/dbg-multithreaded-show-threads.png "ThreadMarker").
218+
219+
2. Press **F11** once to advance the debugger one line of code.
220+
221+
3. Look at the gutter on the left side of the window. On this line, you will see a *thread marker* icon ![Thread Marker](../debugger/media/dbg-thread-marker.png "ThreadMarker") that resembles two cloth threads. The thread marker indicates that a thread is stopped at this location.
222+
223+
Notice that some thread markers will be partly concealed by the breakpoint (which you can remove, if needed).
224+
225+
4. Hover the pointer over the thread marker. A DataTip appears. The DataTip tells you the name and thread ID number for each stopped thread. In this case, the name is probably `<noname>`.
226+
227+
5. Right-click the thread marker to see the available options on the shortcut menu.
228+
229+
## View the Location of Threads
230+
231+
In the **Parallel Stacks** window, you can switch between a Threads view and (for task-based programming) Tasks view.
232+
233+
1. Open the **Parallel Stacks** window by choosing **Debug / Windows / Parallel Stacks**. You should see something similar to this (the exact information will be different depending on the current location of each thread and your programming language).
234+
235+
![Parallel Stacks Window](../debugger/media/dbg-multithreaded-parallel-stacks.png "ParallelStacksWindow")
236+
237+
In this illustration, we see that two threads have entered the `ServerClass.InstanceMethod`, one of which is the active thread (yellow marker). The other thread has stopped in `Thread.Sleep` (indicated by the thread marker icon ![Thread Marker](../debugger/media/dbg-thread-marker.png "ThreadMarker")). In addition, the Main thread (on the left) has stopped on `Thread.Start`, and a new thread (on the right) is also starting (stopped on `ThreadHelper.ThreadStart`).
238+
239+
2. Right-click entries in the **Parallel Stacks** window to see the available options on the shortcut menu.
240+
241+
> [!NOTE]
242+
> If you are more interested in seeing detailed information on each thread such as the type and name of each thread, use the **Threads** window instead. See [Walkthrough: Debug a Multithreaded Application](../debugger/how-to-use-the-threads-window.md).
243+
244+
## Set a Watch on a Variable
245+
246+
1. Open the **Parallel Watch** window by choosing **Debug / Windows / Parallel Watch / Parallel Watch 1**.
247+
248+
2. Click in the 4th column header cell, type `data`, and press Enter.
249+
250+
The values for the data variable for each thread appear in the window.
251+
252+
3. Click in the 5th column header call, type `count`, and press Enter.
253+
254+
The values for the count variable for each thread appear in the window.
255+
256+
![Parallel Watch Window](../debugger/media/dbg-multithreaded-parallel-watch.png "ParallelWatchWindow")
257+
258+
If you don't see this much information yet, try pressing F11 again to advance the execution of the threads in the debugger.
259+
260+
4. Right-click one of the rows in the window to see available options.
261+
262+
## Flagging and Unflagging Threads
263+
You can flag threads that you want to give special attention. Flagging threads is a good way to keep track of important threads and to ignore threads that you do not care about.
264+
265+
#### To flag threads
266+
267+
1. In the code editor, press F11 a few more times until more threads appear in the **Parallel Watch** window.
268+
269+
2. In the **Parallel Watch** window, hold down the SHIFT key and select multiple rows.
270+
271+
3. Right-click and choose **Flag**.
272+
273+
Now, all the selected threads are flagged.
274+
275+
> [!TIP]
276+
> When you have flagged some threads, you can right-click a line of code in the code editor and choose **Run Flagged Threads to Cursor** (make sure that you choose code that all flagged threads will reach). This will pause threads on the selected line of code, making it easier control the order of execution by [freezing and thawing threads](#bkmk_freeze).
277+
278+
4. In the **Parallel Watch** window, find the **Show Only Flagged Threads** icon ![Show Flagged Threads](../debugger/media/dbg-threads-show-flagged.png "ThreadMarker") to the right of the **Show Stacks** list.
279+
280+
The flags icon on the button was dimmed before. Now, it is an active button.
281+
282+
7. Click the **Show Only Flagged Threads** icon.
283+
284+
Only the flagged thread appears in the list now.
285+
286+
#### To unflag threads
287+
288+
You can click the single flag button to toggle back to **Show All Threads** mode. (You can also right-click in the **Parallel Watch** window and choose **Unflag**.)
289+
290+
Flag all the threads again before continuing the next task (in which you will freeze thread execution).
291+
292+
## <a name="bkmk_freeze"></a> Freezing and thawing thread execution
293+
294+
> [!TIP]
295+
> You can freeze and thaw (suspend and resume) threads to control the order in which threads perform work. This can help you resolve concurrency issues such as deadlocks and race conditions.
296+
297+
#### To freeze and unfreeze threads
298+
299+
1. In the **Parallel Watch** window, with all the rows selected, right-click and select **Freeze**.
300+
301+
In the second column, a pair of vertical bars now appear for each row. Those two blue bars indicate that the thread is frozen.
302+
303+
2. Deselect the rows by clicking one row only.
304+
305+
3. Right-click a row and select **Thaw**.
306+
307+
The vertical bars go away on this row, indicating that the thread is no longer frozen.
308+
309+
4. Switch to the code editor and click **F11**. Only the unfrozen thread runs.
310+
311+
The app may also instantiate some new threads. Notice that any new threads are unflagged and are not frozen.
312+
313+
## Follow a Single Thread by using Conditional Breakpoints
314+
315+
Sometimes, it can be helpful to follow the execution of a single thread in the debugger. One way you can do that is by freezing threads that you are not interested in, but in some scenarios you may wish to follow a single thread without freezing other threads (due to the nature of a bug, for example). To follow a thread without freezing other threads you must avoid breaking into code except on the thread that you are interested in. You can do this by setting a conditional breakpoint.
316+
317+
You can set breakpoints on different conditions, such as the thread name or (if you know it) the thread ID. Another method that may be helpful is to set the condition on data that you know will be unique to each thread. This is a common debugging scenario, in which you are more interested in some particular data value than in any particular thread.
318+
319+
#### To follow a single thread
320+
321+
1. Right-click the breakpoint you previously created and choose **Conditions**.
322+
323+
2. In the **Breakpoint Settings** window, type `data == 5` for the conditional expression.
324+
325+
![Conditional Breakpoint](../debugger/media/dbg-multithreaded-conditional-breakpoint.png "ConditionalBreakpoint")
326+
327+
3. Close the **Breakpoint Settings** window.
328+
329+
4. Click the Restart ![Restart App](../debugger/media/dbg-tour-restart.png "RestartApp") button to restart your debugging session.
330+
331+
You will break into code on the thread for which the data variable is 5. Check the active thread (yellow arrow) in the **Parallel Watch** window to verify that.
332+
333+
5. Now, you can step over code (F10) and step into code (F11) and follow the execution of the single thread.
334+
335+
As long as the breakpoint condition is unique to the thread, and the debugger doesn't hit any other breakpoints on other threads, you can step over code and step into code without switching to other threads.
336+
337+
> [!NOTE] If you are more interested in a specific thread, then use a thread name or thread ID for the condition.
338+
339+
## More about the multithreaded debugging windows
340+
341+
#### To switch the active thread
342+
343+
- See [How to: Switch to Another Thread While Debugging](../debugger/how-to-switch-to-another-thread-while-debugging.md)
344+
345+
#### To learn more about the Parallel Stack and Parallel Watch windows
346+
347+
- See [How to: Use the Parallel Stack Window](../debugger/using-the-parallel-stack-window.md)
348+
349+
- See [How to: Use the Parallel Watch Window](../debugger/how-to-use-the-parallel-watch-window.md)
350+
351+
## See Also
352+
[Debug Multithreaded Applications](../debugger/debug-multithreaded-applications-in-visual-studio.md)
353+
[How to: Switch to Another Thread While Debugging](../debugger/how-to-switch-to-another-thread-while-debugging.md)

0 commit comments

Comments
 (0)