As the improvement in desktop computing performance is increasingly reliant on the addition of extra processing cores, rather than on higher clock speeds, parallel programming is becoming more important. When using the .NET framework version 4.0, utilising parallelism is supported via the Task Parallel Library (TPL). The TPL makes is easier to write parallel code with the introduction of the parallel for loop, parallel foreach loop, the Task class and a parallel version of Language-Integrated Query, known as PLINQ.
Adding the above new features to the .NET framework has made the process of creating parallel software less difficult. The second part of the problem of parallelism comes when trying to debug code that is not performing as expected. As there may be many threads of execution running simultaneously, the debugging tools must also be improved. Visual Studio 2010 assists here too, adding new parallel debugging tools, including the Parallel Tasks Window.
This article describes the Parallel Task Window. The screenshot that we will see was created during the execution of the code shown below. Note the comment that shows the position of the breakpoint that was used to break into the code.
static Task _tasks;
static void Main(string args)
_tasks = new Task
Console.WriteLine("All Tasks Complete");
private static void LongTaskA()
Console.WriteLine("Long Task A Started");
Console.WriteLine("Long Task A Complete");
private static void LongTaskB()
Console.WriteLine("Long Task B Started");
Console.WriteLine("Long Task B Complete"); // Add breakpoint here
You'll also need to add using directives for two namespaces:
Parallel Tasks Window
When you pause your executing code in the Visual Studio debugger, usually by adding breakpoints or tracepoints, all of the current parallel tasks are frozen. The Parallel Tasks Window shows all of those tasks in a grid, including tasks that were running at the time that the program was halted and those that were scheduled for execution. You can use the window to access information about the tasks, to organise the tasks by sorting and grouping them and to switch between tasks in order to examine them individually. You can also freeze tasks to prevent them from continuing until you choose to "thaw" them.
Viewing the Parallel Tasks Window
The Parallel Tasks Window can only be viewed when the debugger is in operation. Run the code shown above with the breakpoint in place. Once the breakpoint is hit, display the window by opening the "Debug" Menu, expanding the "Windows" submenu and selecting, "Parallel Tasks". The window should appear similar to the image shown below:
Parallel Tasks Window Columns
The above image shows all of the available columns of the window. You may find that some of these are not visible immediately. If so, you can right-click a column header and choose the columns that you wish to show or hide from the menu that appears. The columns are, from left to right, as follows:
- Flag Column. This column, which has no header text, shows a flag against each active task. You can click the flags to activate or deactivate them. The flags are useful when there are a few tasks that you are particularly interested in. You can flag just those rows and sort or group the grid based upon the flag column.
- Second Column. The second column in the image, also with no header text, can show one of several glyphs. If a yellow arrow is present, the row shows the task that is currently being debugged. Using other debugging windows, such as the Locals and Autos windows, to examine variables will show the values for this task. You can change which of the tasks is current by double-clicking a row or by right-clicking it and selecting, "Switch To Task". The displayed glyph is a white arrow for the task that was current when the breakpoint was hit. Finally, a pause icon is shown for tasks that have been frozen.
- ID. This column shows the unique ID numbers of the tasks.
- Status. This column shows the status of each task. Various statuses are available:
- Running. The task was active when the break occurred.
- Waiting. The task was not running when the code halted. It was waiting to start, waiting for an event to occur, a lock to be released or another task to complete.
- Scheduled. The task was scheduled for execution when the break occurred but had not yet commenced.
- Deadlocked. The task was deadlocked with another thread or task.
- Location. This column shows the fully qualified name of the member being executed when the code was stopped. If you hover the mouse pointer over a cell in this column the call stack for the task is shown.
- Task. This column shows the name of the member called at the start of the task. Tasks that were started with a lambda expression will show the anonymous method name here.
- Parent. For rows that represent child tasks, this column shows the task ID of the parent task. For tasks that are not child tasks the column is blank.
- Thread Assignment. This column shows the ID of the thread that has been assigned to execute the task. It is possible that this value will not be unique as the TPL will allocate multiple tasks to a single thread to try to limit context switching and achieve optimum performance.
- AppDomain. This column shows the application domain for each task.
20 May 2012