翻訳への提案を行います
 
他のユーザーによる提案:

progress indicator
他の提案はありません。
 印刷用ページ       送信     
クリックして評価とフィードバックをお寄せください
MSDN
MSDN ライブラリ
Visual Studio 2010 Beta 2
Visual Studio
Visual Studio でのデバッグ
 チュートリアル: 並列アプリケーションのデバッグ
すべて縮小/すべて展開 すべて縮小
コンテンツの表示:   英語と日本語を並べて表示コンテンツの表示: 英語と日本語を並べて表示
このページは、ベータ版用に機械翻訳されたものです。翻訳者による翻訳は、製品の正規版で提供される予定です。詳細についてはよくある質問 を参照してください。またぜひこちら からアンケートにもご協力ください。
Walkthrough: Debugging a Parallel Application

[This documentation is for preview only, and is subject to change in later releases. Blank topics are included as placeholders.]

This walkthrough shows how to use the Parallel Tasks and Parallel Stacks windows to debug a parallel application. These windows help you understand and verify the runtime behavior of code that uses the Task Parallel Library APIs. This walkthrough provides sample code that has built-in breakpoints. After the code breaks, the walkthrough shows how to use the Parallel Tasks and Parallel Stacks windows to examine it.

This walkthrough teaches these tasks:

  • How to view the call stacks of all threads in one view.

  • How to view the list of System.Threading.Tasks.Task instances that are created in your application.

  • How to view the real call stacks of tasks instead of threads.

  • How to navigate to code from the Parallel Tasks and Parallel Stacks windows.

  • How the windows cope with scale through grouping, zooming, and other related features.

You must have Visual Studio 2010 Beta 2 installed on the computer.

This walkthrough assumes that Just My Code is enabled. On the Tools menu, click Options, expand the Debugging node, select General, and then select Enable Just My Code (Managed only). If you do not set this feature, you can still use this walkthrough, but your results may differ from the illustrations.

C# Sample

If you use the C# sample, this walkthrough also assumes that External Code is hidden. To toggle whether external code is displayed, right-click the Name table header of the Call Stack window, and then select or clear Show External Code. If you do not set this feature, you can still use this walkthrough, but your results may differ from the illustrations.

C++ Sample

If you use the C++ sample, you can ignore references to External Code in this topic. External Code only applies to the C# sample.

Illustrations

The illustrations in this topic recorded on a quad core computer running the C# sample. Although you can use other configurations to complete this walkthrough, the illustrations may differ from what is displayed on your computer.

The sample code in this walkthrough is for an application that does nothing. The goal is just to understand how to use the tool windows to debug a parallel application.

To create the sample project

  1. In Visual Studio, on the File menu, point to New and then click Project.

  2. In the Installed Templates pane, select either Visual C#, Visual Basic, or Visual C++. For the managed languages, ensure that .NET Framework 4 Beta 1 is displayed in the framework box.

  3. Select Console Application and then click OK. Remain in DEBUG configuration, which is the default.

  4. Open the .cpp, .cs, or .vb code file in the project. Delete its contents to create an empty code file.

  5. Paste the following code for your chosen language into the empty code file.

C#
                          using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

class S
{
    staticvoid Main()
    {
        pcount = Environment.ProcessorCount;
        Console.WriteLine("Proc count = " + pcount);
        ThreadPool.SetMinThreads(4, -1);
        ThreadPool.SetMaxThreads(4, -1);

        t1 = new Task(A, 1);
        t2 = new Task(A, 2);
        t3 = new Task(A, 3);
        t4 = new Task(A, 4);
        Console.WriteLine("Starting t1 " + t1.Id.ToString());
        t1.Start();
        Console.WriteLine("Starting t2 " + t2.Id.ToString());
        t2.Start();
        Console.WriteLine("Starting t3 " + t3.Id.ToString());
        t3.Start();
        Console.WriteLine("Starting t4 " + t4.Id.ToString());
        t4.Start();

        Console.ReadLine();
    }

    staticvoid A(object o)
    {
        B(o);
    }
    staticvoid B(object o)
    {
        C(o);
    }
    staticvoid C(object o)
    {
        int temp = (int)o;

        Interlocked.Increment(ref aa);
        while (aa < 4)
        {
            ;
        }

        if (temp == 1)
        {
            // BP1 - all tasks in C
            Debugger.Break();
            waitFor1 = false;
        }
        else
        {
            while (waitFor1)
            {
                ;
            }
        }
        switch (temp)
        {
            case 1:
                D(o);
                break;
            case 2:
                F(o);
                break;
            case 3:
            case 4:
                I(o);
                break;
            default:
                Debug.Assert(false, "fool");
                break;
        }
    }
    staticvoid D(object o)
    {
        E(o);
    }
    staticvoid E(object o)
    {
        // break here at the same time as H and Kwhile (bb < 2)
        {
            ;
        }
        //BP2 - 1 in E, 2 in H, 3 in J, 4 in K
        Debugger.Break();
        Interlocked.Increment(ref bb);

        //after
        L(o);
    }
    staticvoid F(object o)
    {
        G(o);
    }
    staticvoid G(object o)
    {
        H(o);
    }
    staticvoid H(object o)
    {
        // break here at the same time as E and K
        Interlocked.Increment(ref bb);
        Monitor.Enter(mylock);
        while (bb < 3)
        {
            ;
        }
        Monitor.Exit(mylock);
        Thread.SpinWait(1000);

        //after
        L(o);
    }
    staticvoid I(object o)
    {
        J(o);
    }
    staticvoid J(object o)
    {
        int temp2 = (int)o;

        switch (temp2)
        {
            case 3:
                t4.Wait();
                break;
            case 4:
                K(o);
                break;
            default:
                Debug.Assert(false, "fool2");
                break;
        }
    }
    staticvoid K(object o)
    {
        // break here at the same time as E and H
        Interlocked.Increment(ref bb);
        Monitor.Enter(mylock);
        while (bb < 3)
        {
            ;
        }
        Monitor.Exit(mylock);
        Thread.SpinWait(1000);

        //after
        L(o);
    }
    staticvoid L(object oo)
    {
        int temp3 = (int)oo;

        switch (temp3)
        {
            case 1:
                M(oo);
                break;
            case 2:
                N(oo);
                break;
            case 4:
                O(oo);
                break;
            default:
                Debug.Assert(false, "fool3");
                break;
        }
    }
    staticvoid M(object o)
    {
        // breaks here at the same time as N and Q
        Interlocked.Increment(ref cc);
        while (cc < 3)
        {
            ;
        }
        //BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
        Debugger.Break();
        Interlocked.Increment(ref cc);
        while (true)
            Thread.Sleep(500); // for ever
    }
    staticvoid N(object o)
    {
        // breaks here at the same time as M and Q
        Interlocked.Increment(ref cc);
        while (cc < 4)
        {
            ;
        }
        R(o);
    }
    staticvoid O(object o)
    {
        Task t5 = Task.Factory.StartNew(P, TaskCreationOptions.AttachedToParent);
        t5.Wait();
        R(o);
    }
    staticvoid P()
    {
        Console.WriteLine("t5 runs " + Task.CurrentId.ToString());
        Q();
    }
    staticvoid Q()
    {
        // breaks here at the same time as N and M
        Interlocked.Increment(ref cc);
        while (cc < 4)
        {
            ;
        }
        // task 5 dies here freeing task 4 (its parent)
        Console.WriteLine("t5 dies " + Task.CurrentId.ToString());
        waitFor5 = false;
    }
    staticvoid R(object o)
    {
        if ((int)o == 2)
        {
            //wait for task5 to diewhile (waitFor5) { ;}
            Thread.SpinWait(900000);

            int i;
            //spin up all procsfor (i = 0; i < pcount - 4; i++)
            {
                Task t = Task.Factory.StartNew(() => { while (true);});
                Console.WriteLine("Started task " + t.Id.ToString());
            }

            Task.Factory.StartNew(T, i + 1 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 2 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 3 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 4 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 5 + 5, TaskCreationOptions.AttachedToParent); //scheduled//BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died
            Debugger.Break();
        }
        else
        {
            Debug.Assert((int)o == 4);
            t3.Wait();
        }
    }
    staticvoid T(object o)
    {
        Console.WriteLine("Scheduled run " + Task.CurrentId.ToString());
    }
    static Task t1, t2, t3, t4;
    staticint aa = 0;
    staticint bb = 0;
    staticint cc = 0;
    staticbool waitFor1 = true;
    staticbool waitFor5 = true;
    staticint pcount;
    static S mylock = new S();
}
  1. On the File menu, click Save All.

  2. On the Build menu, click Rebuild Solution.

    Notice that there are four calls to Debugger.Break. Therefore, you do not have to insert breakpoints; just running the application will cause it to break in the debugger up to four times.

On the Debug menu, click Start Debugging. Wait for the first breakpoint to be hit.

To view the call stack of a single thread

  1. On the Debug menu, point to Windows and then click Threads. Dock the Threads window at the bottom of Visual Studio.

  2. On the Debug menu, point to Windows and then click Call Stack. Dock the Call Stack window at the bottom Visual Studio.

  3. Double-click a thread in the Threads window to make it current. Current threads have a yellow arrow. When you change the current thread, its call stack is displayed in the Call Stack window.

To examine the Parallel Stacks window

  • On the Debug menu, point to Windows and then click Parallel Stacks. Make sure that Threads is selected in the box at the upper-left corner.

    By using the Parallel Stacks window, you can view multiple call stacks at the same time in one view. The following illustration shows the Parallel Stacks window above the Call Stack window.

    The call stack of the Main thread appears in one box and the call stacks for the other four threads are grouped in another box. Four threads are grouped together because their stack frames share the same method contexts; that is, they are in the same methods: A, B, and C. To view the thread IDs and names of the threads that share the same box, hover over the header (4 Threads). The current thread is displayed in bold, as shown in the following illustration.

    The yellow arrow indicates the active stack frame of the current thread. To get more information, hover over it

    You can set how much detail to show for the stack frames (Module Names, Parameter Types, Parameter Names, Parameter Values, Line Numbers and Byte Offsets) by right-clicking in the Call Stack window.

    A blue highlight around a box indicates that the current thread is part of that box. The current thread is also indicated by the bold stack frame in the tooltip. If you double-click the Main thread in the Threads window, you can observe that the blue highlight in the Parallel Stacks window moves accordingly.

To resume execution until the second breakpoint

  • To resume execution until the second breakpoint is hit, on the Debug menu, click Continue. The following illustration shows the thread tree at the second breakpoint.

    At the first breakpoint, four threads all went from S.A to S.B to S.C methods. That information is still visible in the Parallel Stacks window, but the four threads have progressed further. One of them continued to S.D and then S.E. Another continued to S.F, S.G, and S.H. Two others continued to S.I and S.J, and from there one of them went to S.K and the other continued to non-user External Code.

    You can hover over the box header, for example, 1 Thread or 2 Threads, to see the thread IDs of the threads. You can hover over stack frames to see thread IDs plus other frame details. The blue highlight indicates the current thread and the yellow arrow indicates the active stack frame of the current thread.

    The cloth-threads icon (overlapping blue and red waved lines) indicate the active stack frames of the noncurrent threads. In the Call Stack window, double-click S.B to switch frames. The Parallel Stacks window indicates the current stack frame of the current thread by using a green curved arrow icon.

    In the Threads window, switch between threads and observe that the view in the Parallel Stacks window is updated.

    You can switch to another thread, or to another frame of another thread, by using the shortcut menu in the Parallel Stacks window. For example, right-click S.J, point to Switch To Frame, and then click a command.

    Right-click S.C and point to Switch To Frame. One of the commands has a check mark that indicates the stack frame of the current thread. You can switch to that frame of the same thread (just the green arrow will move) or you can switch to the other thread (the blue highlight will also move). The following illustration shows the submenu.

    When a method context is associated with just one stack frame, the box header displays 1 Thread and you can switch to it by double-clicking. If you double-click a method context that has more than 1 frame associated with it, then the menu automatically pops up. As you hover over the method contexts, notice the black triangle at the right. Clicking that triangle also displays the shortcut menu.

    For large applications that have many threads, you may want to focus on just a subset of threads. The Parallel Stacks window can display call stacks only for flagged threads. On the toolbar, click the Show Only Flagged button next to the list box.

    Next, in the Threads window, flag threads one by one to see how their call stacks appear in the Parallel Stacks window. To flag threads, use the shortcut menu or the first cell of a thread. Click the Show Only Flagged toolbar button again to show all threads.

To resume execution until the third breakpoint

  1. To resume execution until the third breakpoint is hit, on the Debug menu, click Continue.

    When multiple threads are in the same method but the method was not at the beginning of the call stack, the method appears in different boxes. An example at the current breakpoint is S.L, which has three threads in it and appears in three boxes. Double-click S.L.

    Notice that S.L is bold in the other two boxes so that you can see where else it appears. If you want to see which frames call into S.L and which frames it calls, click the Toggle Method View button on the toolbar. The following illustration shows the method view of The Parallel Stacks window.

    Notice how the diagram pivoted on the selected method and positioned it in its own box in the middle of the view. The callees and callers appear on the top and bottom. Click the Toggle Method View button again to leave this mode.

    The shortcut menu of the Parallel Stacks window also has the following other items.

    • Hexadecimal Display toggles the numbers in the tooltips between decimal and hexadecimal.

    • Symbol Load Information and Symbol Settings open the respective dialog boxes.

    • Go To Source Code and Go To Disassembly navigate in the editor to the selected method.

    • Show External Code displays all the frames even if they are not in user code. Try it to see the diagram expand to accommodate the additional frames (which may be dimmed because you do not have symbols for them).

    When you have large diagrams and you step to the next breakpoint, you may want the view to auto scroll to the active stack frame of the current thread; that is, the thread that hit the breakpoint first. In the Parallel Stacks window, make sure that the Auto Scroll to Current Stack Frame button on the toolbar is on.

  2. Before you continue, in the Parallel Stacks window, scroll all the way to the left and all the way down.

To resume execution until the fourth breakpoint

  1. To resume execution until the fourth breakpoint is hit, on the Debug menu, click Continue.

    Notice how the view autoscrolled into place. Switch threads in the Threads window or switch stack frames in the Call Stack window and notice how the view always autoscrolls to the correct frame. Turn off Auto Scroll to Current Tool Frame option and view the difference.

    The overhead view also helps with large diagrams in the Parallel Stacks window. You can see the overhead view by clicking the button between the scroll bars on the lower-right corner of the window, as shown in the following illustration.

    You can move the rectangle to quickly pan around the diagram.

    Another way to move the diagram in any direction is to click a blank area of the diagram and drag it where you want it.

    To zoom in and out of the diagram, press and hold CTRL while you move the mouse wheel. Alternatively, click the Zoom button on the toolbar and then use the Zoom tool.

    You can also view the stacks in a top-down direction instead of bottom-up, by clicking the Tools menu, clicking Options, and then select or clear the option under the Debugging node.

  2. Before you continue, on the Debug menu, click Stop Debugging to end execution.

We recommended that you complete the earlier procedures before you continue.

To restart the application until the first breakpoint is hit

  1. On the Debug menu, click Start Debugging and wait for the first breakpoint to be hit.

  2. On the Debug menu, point to Windows and then click Threads. Dock the Threads window at the bottom of Visual Studio.

  3. On the Debug menu, point to Windows and click Call Stack. Dock the Call Stack window at the bottom Visual Studio.

  4. Double-click a thread in the Threads window to makes it current. Current threads have the yellow arrow. When you change the current thread, the other windows are updated. Next, we will examine tasks.

  5. On the Debug menu, point to Windows and then click Parallel Tasks. The following illustration shows the Parallel Tasks window.

    For each running Task, you can read its ID, which is returned by the same-named property, the ID and name of the thread that runs it, its location (hovering over that displays a tooltip that has the whole call stack). Also, under the Task column, you can see the method that was passed into the task; in other words, the starting point.

    You can sort any column. Notice the sort glyph that indicates the sort column and direction. You can also reorder the columns by dragging them left or right.

    The yellow arrow indicates the current task. You can switch tasks by double-clicking a task or by using the shortcut menu. When you switch tasks, the underlying thread becomes current and the other windows are updated.

    When you manually switch from one task to another, the yellow arrow moves, but a white arrow still shows the task that caused the debugger to break.

To resume execution until the second breakpoint

  • To resume execution until the second breakpoint is hit, on the Debug menu, click Continue.

    Previously, the Status column showed all tasks as Running, but now two of the tasks are Waiting. Tasks can be blocked for many different reasons. In the Status column, hover over a waiting task to learn why it is blocked. For example, in the following illustration, task 3 is waiting on task 4.

    Task 4, in turn, is waiting on a monitor owned by the thread assigned to task 2.

    You can flag a task by clicking the flag in the first column of the Parallel Tasks window.

    You can use flagging to track tasks between different breakpoints in the same debugging session or to filter for tasks whose call stacks are shown in the Parallel Stacks window.

    When you used the Parallel Stacks window earlier, you viewed the application threads. View the Parallel Stacks window again, but this time view the application tasks. Do this by selecting Tasks in the box on the upper left. The following illustration shows the Tasks View.

    Threads that are not currently executing tasks are not shown in the Tasks View of the Parallel Stacks window. Also, for threads that execute tasks, some of the stack frames that are not relevant to tasks are filtered from the top and bottom of the stack.

    View the Parallel Tasks window again. Right-click any column header to see a shortcut menu for the column.

    You can use the shortcut menu to add or remove columns. For example, the AppDomain column is not selected; therefore, it is not displayed in the list. Click Parent. The Parent column appears without values for any of the four tasks.

To resume execution until the third breakpoint

  • To resume execution until the third breakpoint is hit, on the Debug menu, click Continue.

    A new task, task 5, is now running and task 4 is now waiting. You can see why by hovering over the waiting task in the Status window. In the Parent column, notice that task 4 is the parent of task 5.

    To better visualize the parent-child relationship, right-click the Parent column header and then click Parent Child View. You should see the following illustration.

    Notice that task 4 and task 5 are running on the same thread. This information is not displayed in the Threads window; seeing it here is another benefit of the Parallel Tasks window. To confirm this, view the Parallel Stacks window. Make sure that you are viewing Tasks. Locate tasks 4 and 5 by double-clicking them in the Parallel Tasks window. When you do, the blue highlight in the Parallel Stacks window is updated. You can also locate tasks 4 and 5 by scanning the tooltips on the Parallel Stacks window.

    In the Parallel Stacks window, right-click S.P, and then click Go To Thread. The window switches to Threads View and the corresponding frame is in view. You can see both tasks on the same thread.

    This is another benefit of the Tasks View in the Parallel Stacks window, compared to the Threads window.

To resume execution until the fourth breakpoint

  • To resume execution until the third breakpoint is hit, on the Debug menu, click Continue. Click the ID column header to sort by ID. You should see the following illustration.

    Because task 5 has completed, it is no longer displayed. If that is not the case on your computer and the deadlock is not shown, step one time by pressing F11.

    Task 3 and task 4 are now waiting on each other and are deadlocked. There are also 5 new tasks that are children of task 2 and are now scheduled. Scheduled tasks are tasks that have been started in code but have not run yet. Therefore, their Location and Thread Assignment columns are empty.

    View the Parallel Stacks window again. The header of each box has a tooltip that shows the thread IDs and names. Switch to Tasks View in the Parallel Stacks window. Hover over a header to see the task ID and name, and the status of the task, as shown in the following illustration.

    You can group the tasks by column. In the Parallel Tasks window, right-click the Status column header and then click Group by Status. The following illustration shows the Parallel Tasks window grouped by status.

    You can also group by any other column. By grouping tasks, you can focus on a subset of tasks. Each collapsible group has a count of the items that are grouped together. You can also quickly flag all items in the group by clicking the Flag button to the right of the Collapse button.

    The last feature of the Parallel Tasks window to examine is the shortcut menu that is displayed when you right-click a task.

    The shortcut menu displays different commands, depending on the status of the task. The commands may include Copy, Select All, Hexadecimal Display, Switch to Task, Freeze Assigned Thread, Freeze All Threads But This, and Thaw Assigned Thread, and Flag.

    You can freeze the underlying thread of a task, or tasks, or you can freeze all threads except the assigned one. A frozen thread is represented in the Parallel Tasks window as it is in the Threads window, by a blue pause icon.

This walkthrough demonstrated the Parallel Tasks and Parallel Stacks debugger windows. Use these windows on real projects that use multithreaded code. You can examine parallel code written in C++, C#, or Visual Basic.

Visual Studio デバッガー
チュートリアル: 並列アプリケーションのデバッグ

[このドキュメントはプレビュー版であり、後のリリースで変更されることがあります。 空白のトピックは、プレースホルダーとして挿入されています。]

このチュートリアルでは、並列タスクの と 並列スタック ウィンドウを使用して、並列アプリケーションをデバッグする方法を示します。 これらのウィンドウでは、理解し、タスクの並列ライブラリ API を使用するコードの実行時の動作を確認できます。 組み込みのブレークポイントを含むサンプル コードをここに示します。 コードが中断後ことを確認する並列タスクと並列スタック ウィンドウを使用する方法をチュートリアルに示します。

このチュートリアルでは、これらのタスクについて説明します。

  • 1 つのビューですべてのスレッドのコール スタックを表示する方法。

  • System.Threading.Tasks.Task インスタンスは、アプリケーションで作成されますがの一覧を表示する方法。

  • スレッドの代わりにタスクの実際の呼び出しスタックを表示する方法。

  • 並列タスクと並列スタック ウィンドウからコードに移動する方法。

  • 方法、ウィンドウはグループ化、ズーム、 および [その他の関連機能のスケールに対処します。

Visual Studio 2010 Beta 2 のコンピューターにインストールされている必要があります。

このチュートリアルでは [マイ コードのみ その が有効な前提としています。 ツールの メニューの [オプションの をクリックして、デバッグ ノードを展開、 の [全般] を選択し、[有効にする [マイ コードのみ (マネージのみ) します。 この機能を設定しない場合このチュートリアルでは、引き続き使用できますが、結果の図は、得られない可能性があります。

C# のサンプル

C# サンプルを使用している場合このチュートリアルも想定しています外部コードは非表示します。 外部のコードが表示されてかどうかを切り替え、呼び出し履歴 ウィンドウの テーブル ヘッダーを右クリックしオンまたは の [外部コードの表示] をオフにします。 この機能を設定しない場合このチュートリアルでは、引き続き使用できますが、結果の図は、得られない可能性があります。

C++ のサンプル

C++ のサンプルを使用している場合はここで外部のコードへの参照無視できます。 外部のコードだけ C# サンプルに適用されます。

このトピックの図は、C# のサンプルを実行するクワッド コア コンピューターで記録されます。 他の構成を使用してこのチュートリアルを完了することができますの図は、異なる場合がありますコンピューターに表示される内容。

このチュートリアルでサンプル コードは、何もするアプリケーションとしています。 目標は、ツール ウィンドウを使用して、並列アプリケーションをデバッグする方法を理解するだけです。

サンプル プロジェクトを作成するには

  1. Visual Studio で、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。

  2. にインストールされたテンプレートの ペインで、Visual C#、Visual Basic または Visual C++ を選択します。 マネージ言語では、その .NET Framework 4 Beta 1 フレームワーク] ボックスに表示されることを確認します。

  3. のコンソール アプリケーションを選択し、[OK] の を実行します。 デバッグ構成の場合は、既定に残ります。

  4. プロジェクトに .cpp や .cs、.vb のコード ファイルを開きます。 空のコード ファイルを作成するのには、その内容を削除します。

  5. 次のコードを選択した言語は、空のコード ファイルに貼り付けます。

C#
                          using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

class S
{
    staticvoid Main()
    {
        pcount = Environment.ProcessorCount;
        Console.WriteLine("Proc count = " + pcount);
        ThreadPool.SetMinThreads(4, -1);
        ThreadPool.SetMaxThreads(4, -1);

        t1 = new Task(A, 1);
        t2 = new Task(A, 2);
        t3 = new Task(A, 3);
        t4 = new Task(A, 4);
        Console.WriteLine("Starting t1 " + t1.Id.ToString());
        t1.Start();
        Console.WriteLine("Starting t2 " + t2.Id.ToString());
        t2.Start();
        Console.WriteLine("Starting t3 " + t3.Id.ToString());
        t3.Start();
        Console.WriteLine("Starting t4 " + t4.Id.ToString());
        t4.Start();

        Console.ReadLine();
    }

    staticvoid A(object o)
    {
        B(o);
    }
    staticvoid B(object o)
    {
        C(o);
    }
    staticvoid C(object o)
    {
        int temp = (int)o;

        Interlocked.Increment(ref aa);
        while (aa < 4)
        {
            ;
        }

        if (temp == 1)
        {
            // BP1 - all tasks in C
            Debugger.Break();
            waitFor1 = false;
        }
        else
        {
            while (waitFor1)
            {
                ;
            }
        }
        switch (temp)
        {
            case 1:
                D(o);
                break;
            case 2:
                F(o);
                break;
            case 3:
            case 4:
                I(o);
                break;
            default:
                Debug.Assert(false, "fool");
                break;
        }
    }
    staticvoid D(object o)
    {
        E(o);
    }
    staticvoid E(object o)
    {
        // break here at the same time as H and Kwhile (bb < 2)
        {
            ;
        }
        //BP2 - 1 in E, 2 in H, 3 in J, 4 in K
        Debugger.Break();
        Interlocked.Increment(ref bb);

        //after
        L(o);
    }
    staticvoid F(object o)
    {
        G(o);
    }
    staticvoid G(object o)
    {
        H(o);
    }
    staticvoid H(object o)
    {
        // break here at the same time as E and K
        Interlocked.Increment(ref bb);
        Monitor.Enter(mylock);
        while (bb < 3)
        {
            ;
        }
        Monitor.Exit(mylock);
        Thread.SpinWait(1000);

        //after
        L(o);
    }
    staticvoid I(object o)
    {
        J(o);
    }
    staticvoid J(object o)
    {
        int temp2 = (int)o;

        switch (temp2)
        {
            case 3:
                t4.Wait();
                break;
            case 4:
                K(o);
                break;
            default:
                Debug.Assert(false, "fool2");
                break;
        }
    }
    staticvoid K(object o)
    {
        // break here at the same time as E and H
        Interlocked.Increment(ref bb);
        Monitor.Enter(mylock);
        while (bb < 3)
        {
            ;
        }
        Monitor.Exit(mylock);
        Thread.SpinWait(1000);

        //after
        L(o);
    }
    staticvoid L(object oo)
    {
        int temp3 = (int)oo;

        switch (temp3)
        {
            case 1:
                M(oo);
                break;
            case 2:
                N(oo);
                break;
            case 4:
                O(oo);
                break;
            default:
                Debug.Assert(false, "fool3");
                break;
        }
    }
    staticvoid M(object o)
    {
        // breaks here at the same time as N and Q
        Interlocked.Increment(ref cc);
        while (cc < 3)
        {
            ;
        }
        //BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
        Debugger.Break();
        Interlocked.Increment(ref cc);
        while (true)
            Thread.Sleep(500); // for ever
    }
    staticvoid N(object o)
    {
        // breaks here at the same time as M and Q
        Interlocked.Increment(ref cc);
        while (cc < 4)
        {
            ;
        }
        R(o);
    }
    staticvoid O(object o)
    {
        Task t5 = Task.Factory.StartNew(P, TaskCreationOptions.AttachedToParent);
        t5.Wait();
        R(o);
    }
    staticvoid P()
    {
        Console.WriteLine("t5 runs " + Task.CurrentId.ToString());
        Q();
    }
    staticvoid Q()
    {
        // breaks here at the same time as N and M
        Interlocked.Increment(ref cc);
        while (cc < 4)
        {
            ;
        }
        // task 5 dies here freeing task 4 (its parent)
        Console.WriteLine("t5 dies " + Task.CurrentId.ToString());
        waitFor5 = false;
    }
    staticvoid R(object o)
    {
        if ((int)o == 2)
        {
            //wait for task5 to diewhile (waitFor5) { ;}
            Thread.SpinWait(900000);

            int i;
            //spin up all procsfor (i = 0; i < pcount - 4; i++)
            {
                Task t = Task.Factory.StartNew(() => { while (true);});
                Console.WriteLine("Started task " + t.Id.ToString());
            }

            Task.Factory.StartNew(T, i + 1 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 2 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 3 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 4 + 5, TaskCreationOptions.AttachedToParent); //scheduled
            Task.Factory.StartNew(T, i + 5 + 5, TaskCreationOptions.AttachedToParent); //scheduled//BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died
            Debugger.Break();
        }
        else
        {
            Debug.Assert((int)o == 4);
            t3.Wait();
        }
    }
    staticvoid T(object o)
    {
        Console.WriteLine("Scheduled run " + Task.CurrentId.ToString());
    }
    static Task t1, t2, t3, t4;
    staticint aa = 0;
    staticint bb = 0;
    staticint cc = 0;
    staticbool waitFor1 = true;
    staticbool waitFor5 = true;
    staticint pcount;
    static S mylock = new S();
}
  1. [ファイル] メニューの [すべてを保存] をクリックします。

  2. [ビルド] メニューの [ソリューションのリビルド] をクリックします。

    されている Debugger.Break への 4 つの呼び出しがあることがわかります。 したがって、する; のブレークポイントを挿入する必要はありません。だけでアプリケーションを実行、4 回までに、デバッガーで中断するのになります。

[デバッグ] メニューの [デバッグ開始] をクリックします。 最初のブレークポイント ヒットするまで待ちます。

1 つのスレッドのコール スタックを表示するには

  1. [デバッグ] メニューの [ウィンドウ] をポイントし、[スレッド] をクリックします。 Visual Studio の下部にある スレッド ウィンドウをドッキングします。

  2. [デバッグ] メニューの [ウィンドウ] をポイントし、[呼び出し履歴] をクリックします。 Visual Studio の下部にある 呼び出し履歴の ウィンドウをドッキングします。

  3. スレッド ウィンドウに現在のスレッドをダブルクリックします。 現在のスレッドは、黄色の矢印があります。 現在のスレッドを変更すると、コール スタックが呼び出し履歴 ウィンドウに表示されます。

並列スタック ウィンドウを確認するには

  • メニューの [デバッグ、Windows をポイントし、[並列スタック をクリックします。 その スレッド が選択されている、左上隅にあるボックス確認します。

    並列スタック ウィンドウで複数のコール スタックを 1 つのビューで同時に表示できます。 The following illustration shows the Parallel Stacks window above the Call Stack window.

    メイン スレッドのコール スタックが 1 つのボックスに表示され、その他の 4 つのスレッドのコール スタックは別のボックスでグループ化されます。 4 つのスレッド化された、スタック フレームの同じメソッド コンテキスト、共有するためつまり、同じ方法ではです。AB、および C スレッド ID とを 1 つのボックスを共有するスレッドの名前を表示するには、ヘッダー (4 スレッド) をマウスです。 現在のスレッドが表示されるで太字、次の図は、のようにします。

    黄色の矢印は、現在のスレッドのアクティブなスタック フレームを示します。 その上に置きます詳細情報を取得、

    呼び出し履歴ウィンドウで右クリックして ( のモジュール名、パラメーターの型の パラメーター名の パラメーター値の 、行番号の およびバイト オフセット ) のスタック フレームの表示の詳細度を設定できます。

    青のハイライト、ボックスの周囲に指定、現在のスレッドがそのボックスの一部。 現在のスレッドは"、ツール ヒントに太字のスタック フレームによっても示されます。 [スレッド] ウィンドウで、メイン スレッドをダブルクリックした場合は並列スタック ウィンドウで青のハイライトが適切に移動するを確認できます。

2 番目のブレークポイントまで実行を再開するには

  • 2 番目のブレークポイントにヒットするまで実行を再開、でデバッグ メニューの継続 をクリックします。 次の図の 2 番目のブレークポイント、スレッド ツリーに示します。

    最初のブレークポイント、4 つのスレッドをすべてしました S.A から S.B を S.C メソッド。 その情報は 並列スタック ウィンドウで表示されたままですが、4 つのスレッドはさらに進行しています。 S.D および東南続きの 1 つ S.F、S.G、S.H. 続き別 外部コードの非ユーザーに続き、S.K に倒産 S.I を S.J、してそれらが 1 つからの続きする 2 つの他.

    スレッドのスレッドの ID を表示するボックス ヘッダー、たとえば、スレッドの 1 または 2 スレッド、上に置くことができます。 スレッド ID とその他のフレームの詳細を表示するスタック フレーム上に置くことができます。 青のハイライトは、現在のスレッドを示し、黄色の矢印を現在のスレッドのアクティブなスタック フレームを示します。

    布スレッド アイコン (重なり合う線青と赤い waved 線) は、固定のスレッドのアクティブなスタック フレームを示します。 呼び出し履歴 ウィンドウでフレームを切り替える S.B をダブルクリックします。 並列スタック ウィンドウを緑の曲線矢印アイコンを使用して、現在のスレッドの現在のスタック フレームを示します。

    スレッド ウィンドウでスレッドを切り替えるにはし、 並列スタック ウィンドウのビューが更新されることを確認します。

    別のスレッド、または、別のスレッドの別のフレームを切り替えるショートカット メニューを並列スタック ウィンドウでを使用することができます。 たとえば、S.J をマウスの右ボタンでクリックして、 をテキスト枠に切り替え、] コマンドをクリックします。

    S.C をマウスの右ボタンでクリックし、テキスト枠に切り替え をポイントします。 コマンドの 1 つは、現在のスレッドのスタック フレームを示すチェック マークがあります。 切り替えたり (緑色の矢印だけが移動する) 同じスレッドのフレームにしたりできます (青のハイライトは移動も)、他のスレッドを切り替えるには。 次に、サブメニューを示します。

    メソッドのコンテキストを 1 つのスタック フレームに関連付けられた場合、ボックス ヘッダーは 1 スレッド を表示し、切り替えることをダブルクリックするとします。、 場合は、メソッドのコンテキストに関連付けられている 1 つ以上のフレームを含む] をダブルクリックし、メニューの [自動的に表示されます。 上、メソッドのコンテキストに置くと右にある黒い三角形を確認します。 ショートカット メニューを表示もその三角形をクリックします。

    多くのスレッドを持つ大規模なアプリケーション、スレッドのサブセットだけに集中する可能性があります。 並列スタック ウィンドウのみのフラグが設定されたスレッドのコール スタック表示できます。 ツールバーの を表示するフラグ付きのみ 横にあるクリックして、リスト ボックス。

    次に、スレッド ウィンドウで 1 つずつ並列スタック ウィンドウでのコール スタックの表示方法確認するスレッドをフラグです。 スレッド フラグを設定するには、ショートカット メニューの [またはスレッドの最初のセルを使用します。 クリックして を表示するフラグ付きのみ ツールバーの (には、もう一度すべてのスレッドを表示します。

3 番目、ブレークポイントまで実行を再開するには

  1. 3 番目のブレークポイントにヒットするまで実行を再開、でデバッグ メニューの継続 をクリックします。

    複数のスレッドが同じメソッドにはメソッドが、コール スタックの先頭にない、別のボックスに、メソッド表示されます。 現在ブレークポイントで例は S.L、3 つのスレッドにされ、3 つのボックスに表示されます。 S.L. をダブルクリックします。

    S.L が、他の 2 つのボックス内に太字見えますの他の場所を参照することができるようにことを確認します。 S.L にフレームを呼び出すかと呼び出しをフレームを表示する場合は、ツールバーには、方法ビューの表示/非表示 ボタンをクリックします。 次に、並列スタック ウィンドウのメソッドのビューを示します。

    図は、選択メソッドでピボットおよび、ビューの途中で、独自のボックスに、配置方法を確認します。 呼び出し元と callees、上部と下部に表示します。 このモードを終了に 表示/非表示方法ビュー) をクリックします。

    並列スタック ウィンドウのショートカット メニューの [が次の他の項目。

    • 16 進表示 10 進数と 16 進数の間のツールヒントの数値を切り替えます。

    • シンボルの読み込み情報 および設定の記号と特殊文字の は、それぞれのダイアログ ボックスを開きます。

    • ソース コードへ移動 と逆の は、選択したメソッドに、エディターに移動します。

    • ユーザー コードでない場合でも、外部コードの には、すべてのフレームが表示されますが表示されます。 それらの記号があるないためには淡色表示) を追加、フレームに合わせてに展開、ダイアグラムを表示するにやってみましょう。

    大規模なダイアグラムがあり、次のブレークポイントにステップ、; 現在のスレッドのアクティブなスタック フレームに自動スクロールを表示する可能性があります。最初のブレークポイントをヒットしているスレッドは。 並列スタック ウィンドウで、 自動スクロール、ツールバーの [現在のスタック フレーム が上かを確認します。

  2. 並列スタック ウィンドウで、続行する前に、左と下方向にずっとのすべての方法をスクロールします。

4 番目のブレークポイントまで実行を再開するには

  1. 4 番目のブレークポイントにヒットするまで実行を再開、でデバッグ メニューの継続 をクリックします。

    通知方法、ビュー autoscrolled にします。 スレッド ウィンドウ内のスレッドを切り替えたりする方法に注意してください 呼び出し履歴 ウィンドウでのスタック フレームを切り替える、ビューの正しいフレームに autoscrolls 常にします。 自動スクロール オプションのツールの現在のフレームの電源を切りの差異を表示します。

    オーバーヘッドのビューは、並列スタック ウィンドウで大きなダイアグラムとも役立ちます。 表示できます、オーバーヘッド、ウィンドウの左下隅にスクロール バーの間] をクリックして、次の図のようにします。

    すばやく、図の周りをパンする四角形を移動できます。

    任意の方向に、ダイアグラムを移動する別の方法は、ダイアグラムの空白の領域をクリックして目的の場所までドラッグです。

    図との間で、ながら Ctrl キーを押しながらマウス ホイールを移動します。 または、ツールバーの [拡大/縮小] をクリックし、ズーム ツールを使用しています。

    表示、スタック、ボトムアップではなく上から下方向に ツールの メニューのをクリックして オプションをクリックし選択またはできますデバッグ ノードの下オプションをオフにします。

  2. 続行する前に、でデバッグ メニューの [、 デバッグの停止 実行を終了するをクリックします。

続行する前に、以前の手順を完了することおくをお勧めします。

最初のブレークポイントまで、アプリケーションを再起動するには、がヒットします。

  1. メニューの [デバッグ のデバッグの開始をクリックして、最初のブレークポイント ヒットするまで待機します。

  2. [デバッグ] メニューの [ウィンドウ] をポイントし、[スレッド] をクリックします。 Visual Studio の下部にある スレッド ウィンドウをドッキングします。

  3. メニューの [デバッグ、Windows をポイントし、[呼び出し履歴 をクリックします。 Visual Studio の下部にある 呼び出し履歴の ウィンドウをドッキングします。

  4. ウィンドウように現在のスレッドのスレッドをダブルクリックします。 現在のスレッドは、黄色の矢印があります。 現在のスレッドを変更すると、他のウィンドウが更新されます。 次に、タスクは検討します。

  5. メニューの [デバッグ、Windows をポイントし、[タスクの並列 をクリックします。 次の図の並列タスク ウィンドウです。

    各実行中のタスクをその ID は、同じ厳密プロパティ、ID および、(重ねるを表示、全体のコール スタックを含むツールヒント) の位置を実行するスレッドの名前によって返される読み取りできます。 また、タスク 列表示できます; タスクに渡されたするメソッドつまり、開始点。

    任意の列を並べ替えることができます。 並べ替え列および方向を示す、並べ替えグリフを確認します。 左または右にドラッグして、列も並べ替えることができます。

    黄色の矢印は、現在のタスクを示します。 タスクをダブルクリックしてかショートカット メニューを使用して、、タスクを切り替えることができます。 タスク、切り替えるし、基になるスレッドが現在、他のウィンドウが更新されます。

    手動で 1 つのタスクからに切り替える別、黄色の矢印を移動しますが、白の矢印、デバッガーを中断する原因となったタスクを引き続き表示されます。

2 番目のブレークポイントまで実行を再開するには

  • 2 番目のブレークポイントにヒットするまで実行を再開、でデバッグ メニューの継続 をクリックします。

    以前は、状態] 列として実行中、すべてのタスクを表示するが 2 つのタスクの待機ようになりました。 タスクは、多くの異なる理由ブロックできます。 状態 列でがブロックされる理由を説明する待機タスクをマウスです。 待機してたとえば、次の図でタスク 3 がいますタスク 4。

    待機して作業 4 はいます 2 のタスクに割り当てられたスレッドが所有するモニター。

    並列タスク ウィンドウの最初の列で、フラグをクリックして、タスク フラグを設定することができます。

    フラグを同じデバッグ セッションで別のブレークポイントの間でタスクを追跡したりのコール スタックは 並列スタック ウィンドウに表示するタスクのフィルターを使用できます。

    並列スタック ウィンドウを以前使用した場合、アプリケーション スレッドを表示します。 並列スタック ウィンドウのビューが、今度のアプリケーション タスクを表示します。 このためにはタスクの でを選択、上段左側のボックス。 次に、タスク ビューを示します。

    現在のタスクが実行されないスレッドは、並列スタック ウィンドウのタスク ビューで表示されません。 またのタスクを実行するスレッドを上部と、スタックの一番下からフィルター タスクに関係ないされるスタック フレームの一部は。

    並列タスク ウィンドウをもう一度表示します。 列に対するショートカット メニューを表示する列見出しは任意を右クリックします。

    列を追加または削除するには、ショートカット メニューの [を使えます。 たとえば、AppDomain 列は選択できません;したがって、一覧には表示されません。 の親をクリックします。 列は、4 つのタスクの値を含まない表示されます。

3 番目、ブレークポイントまで実行を再開するには

  • 3 番目のブレークポイントにヒットするまで実行を再開、でデバッグ メニューの継続 をクリックします。

    タスク 5、新しいタスクが実行今すぐされタスク 4 は現在待機しています。 状態 ウィンドウで待機している仕事を重ねるして理由を表示できます。 列でそのタスク 4 は作業 5 の親になってを確認します。

    親子関係を視覚化より、 列見出しを右クリックし、 の親の子ビュー。 次の図が表示されます。

    タスク 4 および 5 のタスクが同じスレッドで実行されていることを確認します。 この情報は、スレッド; ウィンドウでは表示されません。並列タスク ウィンドウの別の利点は、ここで表示です。 これを確認するには、並列スタック ウィンドウを表示します。 タスクの を表示していることを確認します。 並列タスク ウィンドウでダブルクリックすることによりタスク 4 および 5 を見つけます。 行うと、青のハイライト並列スタック ウィンドウで更新されます。 タスク 4 および 5 は並列スタック ウィンドウで、ツールヒントをスキャンしても検索できます。

    並列スタック ウィンドウで、S.P を右クリックし、移動スレッド 。 対応するフレームがビューでは、ウィンドウ スレッド ビューに切り替えします。 同じスレッドで両方のタスクを確認できます。

    これはスレッド ウィンドウと比べて、 並列スタック ウィンドウでのタスク ビューの別の利点です。

4 番目のブレークポイントまで実行を再開するには

  • 3 番目のブレークポイントにヒットするまで実行を再開、でデバッグ メニューの継続 をクリックします。 の ID の 列ヘッダーをクリックして ID です。 を並べ替える 次の図が表示されます。

    タスク 5 が完了すると、ためにが表示されなく。 コンピューターにそうでないこと、デッドロックが表示されていない場合は 1 回 F11 キーを押すとステップします。

    タスク 3 とタスク 4 は、互いに待機しているようになりましたはデッドロックが発生します。 また、タスク 2 の子およびを今すぐスケジュールされる 5 つの新しいタスクもあります。 スケジュールされたタスクは、コード内で開始されたがまだ実行されていないタスクです。 したがって、その場所の と スレッドの割り当て 列は空です。

    並列スタック ウィンドウをもう一度表示します。 各ボックスのヘッダーには、スレッド ID と名前を示すツールヒントがあります。 並列スタック ウィンドウでのタスク ビューに切り替えます。 次の図は、のように、タスク ID と、名前と、タスクの状態を表示するヘッダーをマウスです。

    列でタスクをグループ化できます。 並列タスク ウィンドウに、 状態 列見出しを右クリックし、 グループ ステータス で。 次の図の状態別にグループ化、並列タスク ウィンドウです。

    その他の列でグループすることもできます。 タスクのグループ化、によってタスクのサブセットに集中できます。 各折りたたみ可能なグループには、グループ化された項目の数がします。 折りたたみ ボタンの右側に フラグ をクリックして、グループ内のすべての項目をすばやくもフラグことができます。

    調べるには、並列タスク ウィンドウの最後の機能は、タスクを右クリックと表示されるショートカット メニューです。

    ショートカット メニューは、タスクの状態に応じて、異なるコマンドが表示されます。 コピーの 、[すべて選択] を 16 進数表示スイッチ タスク、枠の固定割り当てられたスレッド 、枠の固定すべてのスレッドがこの 、および 割り当てられたスレッドを解放、およびフラグの 場合、コマンドがあります。

    タスク、または、タスクの基になるスレッドを保持することができますか、割り当てられた 1 つを除くすべてのスレッドを保持することができます。 固定されたスレッドが ウィンドウのタスクの並列でスレッド ウィンドウの ではアイコンで表示青 一時停止

このチュートリアルでは、並列タスクの 並列スタック デバッガー ウィンドウを示します。 マルチスレッド コードを使用する実際のプロジェクトでのこれらのウィンドウを使用します。 C++、C# の場合、または Visual Basic で記述された並列のコードを調べてできます。

© 2009 Microsoft Corporation. All rights reserved. 使用条件 | 商標 | プライバシー
Page view tracker