スレッドは、オペレーティング システムがプロセッサ時間を付与する命令のシーケンスです。 オペレーティング システムで実行されているすべてのプロセスは、少なくとも 1 つのスレッドで構成されます。 複数のスレッドを持つプロセスは、マルチスレッドと呼ばれます。
複数のプロセッサ、マルチコア プロセッサ、またはハイパースレッディング プロセスを持つコンピューターでは、複数の同時スレッドを実行できます。 多くのスレッドを使用した並列処理により、プログラムのパフォーマンスが大幅に向上しますが、多くのスレッドを追跡しているため、デバッグが困難になる場合もあります。
完全な並列処理が常に可能であるとは限りません。 スレッドを同期する必要がある場合があります。 あるスレッドが別のスレッドからの結果を待つ必要がある場合や、あるスレッドが別のスレッドが使用しているリソースへの排他的アクセスが必要な場合があります。 同期の問題は、マルチスレッド アプリケーションのバグの一般的な原因です。 場合によっては、スレッドがリソースが使用可能にならないまで待機する場合があります。 その結果、デッドロックと呼ばれる状態 になります。
スレッドとプロセス
スレッド と プロセス は、コンピューター サイエンスの関連概念です。 どちらも、特定の順序で実行する必要がある命令のシーケンスを表します。 ただし、個別のスレッドまたはプロセスの命令は並列で実行できます。
プロセスはオペレーティング システムに存在し、ユーザーがプログラムまたはアプリケーションと見なす内容に対応します。 一方、スレッドはプロセス内に存在します。 このため、スレッドは 軽量プロセスと呼ばれることもあります。 各プロセスは、1 つ以上のスレッドで構成されます。
複数のプロセスが存在すると、コンピューターは一度に複数のタスクを実行できます。 複数のスレッドが存在すると、プロセスで作業を並列に実行できます。 マルチプロセッサがあるコンピューターでは、プロセスまたはスレッドを異なるプロセッサで実行できます。 これにより、真の並列処理が可能になります。
マルチスレッド アプリをデバッグするためのツール
Visual Studio には、マルチスレッド アプリのデバッグに使用するさまざまなツールが用意されています。
スレッドの場合、スレッドをデバッグするための主要なツールは、 並列スタック ウィンドウ、 並列ウォッチ ウィンドウ、ソース ウィンドウのスレッド マーカー、 スレッド ウィンドウ、 デバッグの場所 ツール バーです。 並列スタックのスレッド ビューの詳細については、「スレッド ビューを使用してデッドロックをデバッグする」を参照してください。 Parallel Stacks ウィンドウと Parallel Watch ウィンドウの使用方法については、「マルチスレッド アプリケーションのデバッグを開始する」を参照してください。 作業の開始に関する記事では、スレッド マーカーの使用方法を示します。 また、「 チュートリアル: C++ AMP アプリケーションのデバッグ」も参照してください。
非同期を使用する .NET コードの場合、デバッグの主要なツールは、[並列スタック] ウィンドウの [タスク] ビューです。 開始するには、「 非同期アプリケーションのデバッグ (.NET)」を参照してください。
スレッドの場合、スレッドをデバッグするための主要なツールは、 並列スタック ウィンドウ、 並列ウォッチ ウィンドウ、ソース ウィンドウのスレッド マーカー、 スレッド ウィンドウ、 デバッグの場所 ツール バーです。 並列スタックのスレッド ビューの詳細については、「並列スタック」ウィンドウでスレッドとタスクを表示するを参照してください。 Parallel Stacks ウィンドウと Parallel Watch ウィンドウの使用方法については、「マルチスレッド アプリケーションのデバッグを開始する」を参照してください。 作業の開始に関する記事では、スレッド マーカーの使用方法を示します。 また、「 チュートリアル: C++ AMP アプリケーションのデバッグ」も参照してください。
非同期を使用する .NET コードの場合、デバッグの主要なツールは、[並列スタック] ウィンドウの [タスク] ビューです。 詳細については、「[並列スタック] ウィンドウでスレッドを表示する」を参照してください。
GPU 上のスレッドをデバッグする場合、プライマリ ツールは [GPU スレッド] ウィンドウです。 GPU スレッド ウィンドウを使用する方法を参照してください。
プロセスの場合、主要なツールは、[ プロセスにアタッチ ] ダイアログ ボックス、 プロセス ウィンドウ、および [デバッグの場所 ] ツール バーです。
Visual Studio には強力なブレークポイントとトレースポイントも用意されています。これは、マルチスレッド アプリケーションをデバッグするときに役立ちます。 ブレークポイント条件とフィルターを使用して、個々のスレッドにブレークポイントを配置します。 Tracepoints を使用すると、プログラムの実行を中断せずにトレースし、デッドロックなどの問題を調査できます。 詳細については、「 ブレークポイントアクションとトレースポイント」を参照してください。
ユーザー インターフェイスを持つマルチスレッド アプリケーションのデバッグは特に困難な場合があります。 2 台目のコンピューターでアプリケーションを実行し、リモート デバッグを使用することを検討してください。 詳細については、「 リモート デバッグ」を参照してください。
次の表は、使用可能な情報と、これらの各場所で実行できるアクションを示しています。
ユーザーインターフェース | 利用可能な情報 | 実行できるアクション |
---|---|---|
[プロセスにアタッチ ] ダイアログ ボックス | アタッチできる使用可能なプロセス: - プロセス名 (.exe) - プロセス ID 番号 - メニュー バーのタイトル - 型 (Managed v4.0;マネージド v2.0、v1.1、v1.0;x86;x64;IA64) - ユーザー名 (アカウント名) - セッション番号 |
アタッチするプロセスを選択する リモート コンピューターを選択する リモート コンピューターに接続するためのトランスポートの種類を変更する |
[プロセス] ウィンドウ | アタッチされたプロセス: - プロセス名 - プロセス ID 番号 - プロセス .exe へのパス - メニュー バーのタイトル - 状態 (中断。実行中) - デバッグ (ネイティブ、マネージドなど)。 - トランスポートの種類 (既定、認証なしのネイティブ) - トランスポート修飾子 (リモート コンピューター) |
ツール -添付する -切り離す -終了する ショートカット メニュー: -添付する -切り離す - デバッグが停止したときにデタッチする -終了する |
デバッグの場所 ツール バー | - 現在のプロセス - アプリケーションを中断する - アプリケーションを再開する - アプリケーションを中断してシャットダウンする - 現在のスレッド - 現在のスレッド フラグの状態を切り替える - フラグ付きスレッドのみを表示する - 現在のプロセスのみを表示する - 現在のスタック フレーム |
- 別のプロセスに切り替える - アプリケーションを一時停止、再開、またはシャットダウンする - 現在のプロセス内の別のスレッドに切り替える - 現在のスレッド内の別のスタック フレームに切り替える - 現在のスレッドにフラグを設定またはフラグ解除する - フラグ付きスレッドのみを表示する - 現在のプロセスのみを表示する |
[並列スタック] ウィンドウ | - 1 つのウィンドウ内の複数のスレッドの呼び出し履歴。 - 各スレッドのアクティブなスタック フレーム。 - 任意のメソッドの呼び出し元と呼び出し元。 - デッドロック検出 |
- 指定されたスレッドをフィルターで除外する - 外部コード スタックを除外する - タスク ビューに切り替える - スレッドにフラグを設定またはフラグ解除する -ズーム - スタック フレームのコピー - すべてのスタックをイメージとして保存/エクスポートする |
[並列ウォッチ ] ウィンドウ | - フラグ列。特別な注意を払うスレッドをマークできます。 - 選択したフレームを矢印で示すフレーム列。 - コンピューター、プロセス、タイル、タスク、スレッドを表示できる構成可能な列。 |
- スレッドにフラグを設定またはフラグ解除する - フラグ付きスレッドのみを表示する - フレームの切り替え - 列を並べ替える - スレッドをグループ化する - スレッドを凍結または解凍する - [並列ウォッチ] ウィンドウでデータをエクスポートする |
[スレッド] ウィンドウ | 現在のプロセス内のスレッド: - スレッド ID - マネージド ID - カテゴリ (メイン スレッド、インターフェイス スレッド、リモート プロシージャ呼び出しハンドラー、またはワーカー スレッド) - スレッド名 - スレッドが作成される場所 -優先権 - Affinity Mask - 中断された数 - プロセス名 - フラグ インジケーター - 中断インジケーター |
ツール -捜索 - 検索呼び出し履歴 - マイ コードのみにフラグを設定する - カスタム モジュールの選択にフラグを設定する - グループ化 -列 - 呼び出し履歴の展開/折りたたみ - グループの展開/折りたたみ - スレッドの凍結/解凍 ショートカット メニュー: - ソースにスレッドを表示する - スレッドに切り替える - 実行中のスレッドを固定する - 凍結したスレッドを解凍する - スレッドに追加の調査のフラグを設定する - スレッドのフラグ解除 - スレッドの名前を変更する - スレッドの表示と非表示を切り替える その他のアクション: - データヒント内のスレッドの呼び出し履歴を表示する |
ソース ウィンドウ | 左側の余白のスレッド インジケーターは、1 つまたは複数のスレッドを示します (既定では、 スレッド ウィンドウのショートカット メニューを使用してオンになっています) | ショートカット メニュー: - スレッドに切り替える - スレッドに追加の調査のフラグを設定する - スレッドのフラグ解除 |
[タスク] ウィンドウ | - タスク ID、タスクの状態 (スケジュール済み、実行中、待機中、デッドロック済み)、タスクに割り当てられているスレッドなど、 Task オブジェクトに関する情報を表示します。 - 呼び出し履歴内の現在の場所。 - 作成時にタスクに渡されるデリゲート |
- 現在のタスクに切り替える - タスクにフラグを設定またはフラグ解除する - タスクを凍結または解凍する |
GPU スレッド ウィンドウ | - フラグ列。特別な注意を払うスレッドをマークできます。 - 現在のスレッド列。黄色の矢印が現在のスレッドを示します。 - スレッド数 列。同じ場所にあるスレッドの数が表示されます。 - 行 列。スレッドの各グループが配置されているコード行が表示されます。 - Address 列。スレッドの各グループが配置されている命令アドレスが表示されます。 - Location 列。アドレスのコード内の場所です。 - スレッドがアクティブかブロックかを示す [状態] 列。 - タイル 列。行内のスレッドのタイル インデックスが表示されます。 |
- 別のスレッドに変更する - 特定のタイルとスレッドを表示する - 列を表示または非表示にする - 列で並べ替える - スレッドをグループ化する - スレッドを凍結または解凍する - スレッドにフラグを設定またはフラグ解除する - フラグ付きスレッドのみを表示する |