前回は実行優先度の高いプロセスを探し出し,Excelシートに表示しました。今回は,プロセスと密接な関係にあるスレッド情報を収集し,同じように,Excelシート上に表示します。スレッドにも実行優先度があるのでしょうか。さっそく,Excelプログラミングを楽しみながら,スレッドの動きを追ってみましょう。

図1●サンプル・プログラムの実行結果

今回のサンプル・プログラム

 まずはいつものように,サンプル・プログラムをこちらからダウンロードし,実行してみましょう。筆者のWindows XP SP2+Excel2003環境では,図1[拡大表示]のような情報が返されます。

 この画面は,簡単に言うと,Windowsが内部で管理しているスレッドのうち,30個のスレッドを列挙し,それぞれの関連情報を表示しています。サンプル・プログラムの技術的な説明は後ほど行いますから,まずは,皆さんの環境で実行してみてください。

 筆者の環境では「Total Count:」欄の数値が350となっていますが,皆さんの環境ではどの程度でしょうか。各種のアプリケーションやサービスなどを起動していると,この欄の数値はかなり大きな値になっているはずです。「Total Count:」欄の数値は,現在作成されているスレッド総数を示しています。この数値は,動的に変化します。

 画面を見ると分かるように,実際のスレッド情報はテーブルとして整理されています。テーブルには「状態」,「待ち理由」,あるいは「現在の優先度」といった各種フィールドが用意され,いろいろな数値が書き込まれています。これらの数値の意味は,後で説明します。

図2●Windowsファイアウオール・プロセスが内部で作成しているスレッド情報
図3●「SVCHOST.EXE」プロセスが内部で作り出しているスレッド情報

 それではここで,Windowsファイアウオール・プロセス(ALG.EXE)が内部で作成しているスレッド情報を収集し,表示してみましょう。筆者の環境では,図2[拡大表示]のような情報が返されました。

 この画面情報を見ると,Windowsファイアウオール・プロセスは5個のスレッドを内部で作成していることが分かります。意外と少ないですね。問題は5個のスレッドのうちの,どのスレッドが現在実行中かということですが,基本的には,「待ち理由」が0で,「現在の優先度」値が最も高いもの,といってよいでしょう。この場合は,1番目のスレッドが「現在実行中」ということになります。ただし,取得できる数値はあくまでもスレッドの実行概要を知るための目安であり,正確なものではありません。より正確な情報収集方法については後ほど紹介します。

 それでは今度は,前回取り上げた「SVCHOST.EXE」プロセスが内部で作り出しているスレッド情報を表示してみます(図3[拡大表示])。

 SVCHOST.EXEという名称のプロセスは7個ありますが,そのうちの1つは70個を超えるスレッドを内部で作成しています。興味のある方は,お時間のあるときに7個すべてのプロセスのスレッド情報を表示させてみるとよいでしょう。

サンプル・プログラムの技術背景

 今回のサンプル・プログラムは,特定のプロセスが内部で作成しているスレッド情報を収集し,Excelシート上に表示してきます。技術的には,350を超えるスレッドの中から,プロセス識別子を絞り込み条件として設定し,目的のプロセスのスレッドを探し出しています。例えば,ソースコード内では次のような条件を指定しています。

If (fStop < 100) And (oObject_2.StartAddress <> 0) And (oObject_2.ProcessHandle = "636") Then

 今回のサンプル・プログラムを使用するときには,「oObject_2.ProcessHandle = "636"」の"636"という部分を変更するようにしてください。使用できる数値はプロセス識別子というものです。プロセス識別子は,前回紹介したNo34.vbsサンプル・プログラムを起動し,取得してください(ProcessIdあるいはHandle欄の値)。

 また,一部のプロセスは膨大な数のスレッドを内部で作り出していますから,筆者は「fStop < 100」という具合に,列挙するスレッド数の上限を設定しています。この数値を小さくすれするほど,サンプル・プログラムは短時間で終了します。

 それでは次に,Excelへの表示を担当するコード部分を説明しておきます。ソースコードを見ると一見難しそうな操作を行っているようですが,筆者はExcel初心者ということもあり,無闇に前に進まずに,これまで学習した技術を確実に身に付けるように努めています。さらに経験を積んでいけば,よりすっきりとしたコードが完成すると思います。

 筆者は,何かを新たに学習する際には,何よりも基本をしっかり身に付ける方針で臨むことにしています。「待ち理由」などのフィールド名の表示では背景色と前景色を明示的に指定していますが,その指定は次のようなコードで実装しています。

oTemp.Cells(i,1).Value = "ThreadNo"
oTemp.Cells(i,2).Value = "状態"
oTemp.Cells(i,3).Value = "待ち理由"
oTemp.Cells(i,4).Value = "現在の優先度"
oTemp.Range(oTemp.Cells(i,1),oTemp.Cells(i,4)).Interior.ColorIndex = 10
oTemp.Range(oTemp.Cells(i,1),oTemp.Cells(i,4)).Font.Name = "MS Pゴシック"
oTemp.Range(oTemp.Cells(i,1),oTemp.Cells(i,4)).Font.FontStyle = "太字"
oTemp.Range(oTemp.Cells(i,1),oTemp.Cells(i,4)).Font.Size = 10
oTemp.Range(oTemp.Cells(i,1),oTemp.Cells(i,4)).Font.ColorIndex = 6

 筆者はこれまでRangeオブジェクトの意味を今ひとつ理解できませんでしたが,前回紹介したRangeオブジェクト解釈を素直に応用しています。参考になれば,幸いです。後日お時間のあるときに自分の手で数値をいろいろ変更してみてください。ソースコード内ではExcel関数なども使用していますが,詳しい説明は後の連載で説明する予定です。

高い精度でスレッド数を返す第2サンプル・プログラム

 それでは最後に「待ち理由」などのフィールドの意味について触れておきます。プロセスとスレッドに関しては,こちらの記事こちらの記事を公開していますので,参考にしてください。

図4●第2サンプル・プログラム「ListThreads.hta」の実行結果

 今回は「現在の優先度」フィールドの意味を説明します。図4[拡大表示]の画面をご覧ください。この画面情報を見ると分かるように,優先度が8から24まで一気に3倍も引き上げられています。この引き上げは,Windowsのスケジューラという機能が担当するといわれます。「現在の優先度」値が大きければ大きいだけ,優先的に実行されることになります。

 このような画面情報は,今回の第2サンプル・プログラム「ListThreads.hta」を実行すると取得できます。第2サンプルは,スレッドが作成されるタイミングで必要なスレッド情報を返してきます。お時間のあるときにぜひ試してみてください。スレッドを内部で多数作成する,例えば,Internet Explorer(IE)やWindows Media Playerなどのスレッド情報を収集してみると面白いと思います。目的のプログラムを起動する前に第2サンプル・プログラムを実行しておくと,多数のスレッドが作成される様子がはっきり分かります。

 一般的には,機能豊富なアプリケーションは,内部で多くのスレッドを作成することになります。IEはインターネット情報を画面に表示しながら,その一方で,プリンタから閲覧情報を印刷するようなことができます。2つの異なる機能が同時に利用できる背景では,複数のスレッドが活動しているわけです。

 しかしスレッドの活動場所であるコンピュータは,有限資源で構成されています(例えば,CPUが一個しかない,など)。つまり,スレッドの活動はいろいろな制約を受けています。各スレッドが受ける制約の内容を示しているのが「状態」フィールドと「待ち理由」フィールドなのです。これら2つのフィールドの詳しい説明は,こちらのサイトで公開されています。お時間のあるときに自分のマシン内のスレッドの活動内容を調べてみてはいかがでしょうか。メモリー増設やマシンの買い替えの必要性などを判断する材料が得られるかもしれません。

 このようなスレッド・ベースの分析能力を身に付けておけば,購入予定のアプリケーションを事前に評価し,現在のマシン・スペックに応じたアプリケーション製品を購入できるようになります。インターネットから試用版をダウンロードし,動作中のスレッドの活動内容を調べれば,そのアプリケーションが自分の現在のマシンで快適に動作するかどうかを購入前に(かなりの精度で)判定できると思います。友人に助言を求められた場合などは,「待ちスレッド数が多いから,このソフトを購入する前に,現在のメモリー量を増やしておいたほうが得策だよ」などと,ITプロフェッショナルにふさわしい見解を述べることもできるようになるでしょう。

 第2サンプル・プログラムは,スレッドが作成されるタイミングで,技術的には非同期にスレッド情報を返してくれますから,第1サンプル・プログラムでは収集できない情報も返してくれます。ある意味では,第2サンプル・プログラムが返してくれる情報の方が,精度が高い,といってよいでしょう。第2サンプル・プログラムには次のようなコードが記述されています。

szQuery = "SELECT * FROM __InstanceCreationEvent WITHIN 1 "
szQuery = szQuery + "WHERE TargetInstance ISA 'Win32_Thread'"

 日ごろデータベースを使用している方は,「これはSQLのSelect文だろう」とちょっと驚かれるかもしれません。まさにその通りですが,WMI Query Language,略して,WQLといいます。WQLに興味のある方は,こちらのサイトを参考にするとよいでしょう。オブジェクト指向に精通している人は,「TargetInstance ISA 'Win32_Thread'」のISAに自然に注意が向くと思います。この場合のISAは,「Win32_Threadクラスの資産を継承するクラスのインスタンス」という意味です。

今回のまとめ

  • プロセスとスレッドは密接な関係にある
  • プロセスと同じように,スレッドにも実行優先度がある
  • 学習した内容は着実に理解することが大切である
  • SQLやオブジェクト指向理論はいろいろなところで応用されている

 今回は以上で終了です。次回またお会いいたしましょう。ごきげんよう!