Debugging Your Code

 < Day Day Up > 



Usually, when you test your application and see that its behavior is not what you expect it to be, you start examining more carefully the code written. If you are using Visual Studio .NET to create your application, it provides many amazing tools to visually debug the application. In addition, whatever language you choose to develop your application in, it will use the same debugger with the same tools. Moreover, the basic debugger's functionalities have been inherited from the Visual Basic 6 and Visual C++ IDEs, resulting in something that should be familiar for most developers. However, we will not spend too much time on the debugger in general, and will focus this discussion mostly on those features directly relevant to threading.

The new debugger provides:

  • The same tool to debug different applications created using different languages, and the ability to debug applications written in mixed languages

  • The ability to debug SQL Server stored procedures

  • The ability to debug .NET Framework and Win32 native code, so that if you are debugging your Visual C# .NET application and your thread uses a COM+ component, you can debug both the applications using the same debugger

  • A more powerful and enhanced remote debugger

If you already have experience with the Visual Basic 6 debugger, you will know that some functionality has been removed. The most relevant is the ability to change the code and continue with its execution. Using the Visual Studio .NET debugger, this feature is no longer available, because each modification to the code requires a new compilation.

In this section of the book, we will analyze the debugging tools provided by the Visual Studio .NET IDE that are especially useful during the testing and error discovery phase of multithreaded application development.

Visual Studio .NET Debugger

Using the Visual Studio .NET debugger, as you know, you can break the execution of your application at a specified point simply by inserting a breakpoint near the line of the code you wish to inspect. When the application is suspended, the debugger provides many tools to examine and edit the content of variables, examine the memory and call stack, and more.

Configuring Debugger Parameters

In order to make use of the Visual Studio .NET debugger, you have to build the application using the Debug configuration. In that way, you will fill the application with symbolic debugging information rather than optimize the code. When everything appears to work fine, you would release your application after recompiling the code, choosing the Release configuration, which removes debugging information and optimizes the code.

When a new debugger session begins, a lot of resources are loaded into the memory. In fact, the debugger fills the memory with various code to allow us to debug unmanaged code, SQL Server stored procedures, and more. It is therefore a good idea to remove these features when you don't need them. You can change the debugger's settings inside the Property Pages dialog box that can be found by right-clicking on the project in the Solution Explorer and selecting Properties. For a Windows application, the following dialog box will appear:

click to expand

After compiling a Debug configured project, the output directory will contain the exe or dll file and a pdb (program database) file. Because IL keeps the values of parameters and private members inside arrays, the original names of these variables are lost - as well as some other information relevant to debugging. When a project is compiled for debugging, or the /debug:full switch is used on the command-line compiler, a pdb file is generated at the same time. The exe or dll file contains an absolute path pointing to the pdb file and if the debugger doesn't find the program database file, it starts to search in the same application path and in the directory specified in the Property Pages dialog box. Finally, if the debugger can't find the pdb file in any directory, it will regenerate a new one.

Debugger Windows

Once you have loaded your project into Visual Studio .NET you are ready to debug your application by simply running it, waiting for the code to reach a breakpoint, then using either the F10 or F11 key to step over and step into method calls in our code, respectively. If you are not working with the release version of your application, you will see the IDE showing many docked windows. During your debugging session these windows will be filled with the variables' values, objects' dumps, call stack, disassembly code, and more. Let's start examining more closely these debugging tools, and how they can be used to assist in the debugging of your threaded application.

The Locals Window

This window allows you to examine and modify each variable's content defined locally in the method you are debugging (including parameters to the method). For example, debugging the following Main() method of TraceSwitchExample, you will retrieve just the content of two variables: fs and t, as shown in the following screenshot:

click to expand

You can activate this window selecting the Debug | Window | Locals menu, or you can press Ctrl+Alt+V, release, and press L.

The Watch Window

You can drag variables from the source code and drop them over the Watch window in order to inspect their values and structure. In the following screenshot, a BooleanSwitch object from an example later in the chapter has been dropped into the window.

click to expand

You can expand tree nodes by clicking the plus sign and then examine and change object property values. You can activate up to four Watch windows by pressing Ctrl+Alt+W, then releasing, and pressing a key between 1 and 4.

You can also add a variable to the Watch window by selecting it in the source code and choosing Add Watch from the context menu.

The Command Window - Immediate Window

This window provides a text field where you can query a variable's contents and change variable values. When you need to retrieve the variable's content you have to use a question mark before the expression. In the following screenshot, the Enabled property of the BooleanSwitch object has been examined, changed to false, and displayed again.

click to expand

In addition, this window allows you to make use of various IDE commands, such as creating a new file or project, finding a string, or whatever else you usually do within the Visual Studio .NET menu. To switch from Immediate mode to Command mode you simply have to write the >cmd statement. Once in Command mode, you will be assisted by the IDE in finding the desired commands by the IntelliSense functionality. You switch back to Immediate mode by using the >immed command.

You can activate this window by selecting Debug | Window | Immediate, or you can press Ctrl+Alt+I.

Stepping Through the Code

Now that we have briefly described the more useful debugger windows, we can focus our attention on code navigation. The Visual Studio .NET debugger allows developers to step between code lines of both single and multiple source code files, observing the program behavior at run time. Moreover, you can debug unmanaged code and Microsoft SQL Server stored procedures. The debugger provides three different ways to step through the code:

  • Step Into: Pressing the F11 key you will go through the code one step at a time, entering method bodies that you find on your way (where source code and debug symbols are available).

  • Step Over: Pressing the F10 key you will go one step forward in the code executing every method you encounter but without stepping into it (executing the method as one line).

  • Step Out: Pressing Shift+F11, you will execute all the remaining code within the body of the method that you are currently stepped into, and step onto the next line in the method that called it.

Each time you step to the next line of code by pressing these keys, you are executing the highlighted code.

Another useful feature provided by the Visual Studio .NET debugger is the Run To Cursor functionality. Selecting it from the context menu over the source code, you can execute all the lines between the highlighted line and the line where the cursor is placed.

Finally, the Visual Studio .NET debugger provides a way to change the execution point of our application. You can decide to move your application's execution point by launching the debugger and choosing the Set Next Statement item in the context menu. Be careful when using this feature, because every line of code between the old and the new position will fail to be executed.

Setting Breakpoints

In large source code applications, it is not practical to step through all the preceding code before arriving at the method you are interested in debugging. The debugger offers the possibility to set breakpoints in the code. As the name says, a breakpoint is a point where the execution of your program is to be suspended. You can specify breakpoints both before and after launching the debugger session, by simply placing the cursor on the line and pressing the F9 key - or by clicking in the left margin. A red highlight will be placed over the line to let you know that you have just added a breakpoint to the code, and a glyph will be added to the left margin of the source window. In order to remove a breakpoint you can either click over the glyph or press the F9 key again.

You can manage all the set breakpoints from a single dialog by using the Breakpoints window.

click to expand

Using this window, you can add a new breakpoint, delete one or all breakpoints, disable all breakpoints, add and remove window's columns, and view breakpoint properties.

start sidebar

By using breakpoints, you can suspend execution of a thread and examine its current stackframe contents.

end sidebar

Selecting the breakpoint properties option from the window above a new dialog box will be shown and you can specify to activate a breakpoint only when a specific variable changes its content. You have to specify the variable's name choosing the has changed radio button in the breakpoint property pages. This again can be useful in threaded scenarios, as you can detect when something unexpected occurs.

Finally, the Hit Count... button from the same dialog box allows developers to enable a breakpoint only when it has reached the specified hit count. Again this is useful in debugging threads as it allows you to see how? often a thread is spawned.

click to expand

From the combo box, you can select the condition that you want to assign to the breakpoint. For example, you can activate the breakpoint in a loop only when you are near to exiting from it. You can select the break when the hit count is equal to an item by assigning a value to the text field that will appear next to the combobox.

In order to execute all the code lines until the breakpoint is reached you have to press the F5 key, select the Debug | Start menu, or press the Start button on the standard toolbar.

Debugging Threads

The Visual Studio .NET debugger provides a special window to manage threads during debugging sessions. You can display this window by selecting Debug | Windows | Threads, or by pressing Ctrl+Alt+H.

click to expand

The Threads window contains the following columns:

Column name

Description

ID

The thread's unique identifier assigned by the operating system.

Name

The thread's name. You can specify it in the code using the Name property of the Thread object.

Location

The method or memory address in which the thread is currently executing.

Priority

The thread's priority.

Suspend

A counter for determining how often the thread has been suspended. The counter zero in the screenshot above indicates that the thread has never been suspended.

You can switch between threads by simply double-clicking on the item within the Threads window. Moreover, by right-clicking on a thread, you can choose the Freeze menu item that will pause the thread's execution. To roll back the frozen thread state, you select the Thaw menu item.



 < Day Day Up > 



C# Threading Handbook
C# Threading Handbook
ISBN: 1861008295
EAN: 2147483647
Year: 2003
Pages: 74

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net