執筆者: インフラジスティックス・ジャパン株式会社 池原 大然

動作確認環境: Visual Studio 2010、.NET Framework 2.0、Windows 7 Enterprise 32 bit

更新日: 2010 年 6 月18 日


CPU の使用率、メモリの使用状況など現在のパフォーマンス データを計測する方法として、System.Diagnostics.PerformanceCounter を使用する方法があります。このカウンタ情報はコンピュータ名、カテゴリ名、カテゴリ インスタンス名、カウンタ名の 4 つの要素から構成されています。また、特定の間隔で処理を行う場合、.NET クラス ライブラリでは System.Threading.TimerSystem.Timers.TimerSystem.Windows.Forms.TimerSystem.Windows.Threading.DispatcherTimer 各クラスが用意されています。例として、System.Threading.Timer クラスはコール バック メソッドを使用しスレッドプール スレッドがサービスを提供する軽量なタイマーです。

下記のサンプル コードは 1 秒おきに現在の CPU 使用率を表示するコードです。

Visual Basic
Imports System.Threading

Module Module1

    Sub Main()
        Using pc As New PerformanceCounter("Processor", "% Processor Time", "_Total", True)
            Dim tDelegate As New Threading.TimerCallback(AddressOf GetCpuUsage)

            Using oTimer As New Timer(tDelegate, pc, 0, 1000)
                Thread.Sleep(30000)
            End Using

        End Using
        Console.WriteLine("Timer を停止しました。終了するには何かキーを押してください。")
        Console.Read()
    End Sub


    Sub GetCpuUsage(ByVal state As Object)
        Dim pc As PerformanceCounter = CType(state, PerformanceCounter)
        If pc IsNot Nothing Then
            Console.WriteLine(String.Format("現在のCPU使用率は {0:f}% です。", pc.NextValue()))
        End If
    End Sub
End Module
 

このコードでは、まず、PerformanceCounter の初期化を行い、その際に、CategoryNameCounterNameInstanceName を指定することで CPU 使用率の計測を開始します。

Visual Basic
pc As New PerformanceCounter("Processor", "% Processor Time", "_Total", True)
 

なお、現在のローカル マシンのカテゴリ、インスタンスについては、PerformanceCounterCategory.GetCategories メソッド、PerformanceCounterCategory.GetInstanceNames メソッドにて取得することが可能です。

Visual Basic
For Each category In PerformanceCounterCategory.GetCategories()
Console.WriteLine(category.CategoryName)
      Dim instances As String() = category.GetInstanceNames()
      If instances.Length > 1 Then
For i As Integer = 0 To instances.Length - 1
                Console.Write(vbTab)
                Console.WriteLine(instances(i))
           Next
    End If
Next
 

次に、タイマーに設定した間隔で実行するコールバック メソッドを定義する必要があります。今回は GetCpuUsage というメソッドにて先ほどの PerformanceCounter を使用し、CPU の使用率を計測するように設定しています。

Visual Basic
Dim tDelegate As New Threading.TimerCallback(AddressOf GetCpuUsage)
 
Visual Basic
Sub GetCpuUsage(ByVal state As Object)
    Dim pc As PerformanceCounter = CType(state, PerformanceCounter)
    If pc IsNot Nothing Then
        Console.WriteLine(String.Format("現在のCPU使用率は {0:f}% です。", pc.NextValue()))
    End If
End Sub
 

最後に System.Threading.Timer のインスタンスを作成します。このコンストラクタへの引数として、コールバック メソッド、コールバック メソッドへの引数 (ここでは PerformanceCounter オブジェクト)、コールバック メソッド開始までの遅延時間、タイマーの間隔を指定します。今回は、1 秒おきにコールバック メソッドを呼び出しています。

Visual Basic
oTimer As New Timer(tDelegate, pc, 0, 1000)
 

実行結果の抜粋は下記の通りです。

現在の CPU 使用率は 0.00% です。
現在の CPU 使用率は 9.52% です。
現在の CPU 使用率は 3.07% です。

... (省略)

現在の CPU 使用率は 16.15% です。
Timer を停止しました。終了するには何かキーを押してください。

上記の例では、コンソール アプリケーションからの利用のため、System.Threading.Timer クラスを使用しましたが、.NET Framework においては目的に応じてタイマーを使い分けることが可能です。ユーザー インターフェースを持つアプリケーションにおいては数十 ms の精度での更新が不要な場合もあるかと思われます。

そのような場合、Windows フォームにおいては System.Windows.Forms.Timer を、WPF (Windows Presentation Framework) においては System.Windows.Threading.DispatcherTimer を利用することが好ましいでしょう。

Windows フォームにおける System.Windows.Forms.Timer の精度は低いですが、イベント ハンドラーは必ずユーザー インターフェース スレッドで発生するため、コントロールを操作する場合の扱いが容易です。

WPF における System.Windows.Threading.DispatcherTimer も、イベントがユーザー インターフェース スレッドで発生する、目的に合わせて優先度を設定できるといった特徴を持っています。

System.Timers.Timer クラスは サーバー環境での実行に適しており、マルチスレッド環境でワーカー スレッドと共に使用するようにデザインされています。タイマーに設定した時間の間隔で Elapsed イベントを発生させるため、このイベント ハンドラー内で処理を記述することが可能です。同じ処理を行うコードは下記の通りです。

Visual Basic
Imports System.Threading

Module Module1
    Dim pc = New PerformanceCounter("Processor", "% Processor Time", "_Total", True)

    Sub Main()
        Try
            Using sTimer As New System.Timers.Timer(1000)
                AddHandler sTimer.Elapsed, AddressOf oTimer_Elapsed
                sTimer.Start()
                Thread.Sleep(30000)
                sTimer.Stop()
            End Using

            Console.WriteLine("Timer を停止しました。終了するには何かキーを押してください。")
            Console.Read()
        Finally
            pc.Dispose()
        End Try
    End Sub

    Private Sub oTimer_Elapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
        Console.WriteLine(String.Format("現在のCPU使用率は {0:f}% です。", pc.NextValue()))
    End Sub
End Module
 

関連リンク


Code Recipe Code Recipe

ページのトップへ