[BlueLeaf1336]> PROBLEMS> BluesBoostCamp>

BluesBoostCamp > APIの使い方勉強

historyTOP

2007/10/11:自分自身に GetPriorityClass / GetThreadPriority
2007/10/16:自分自身に SetPriorityClass / SetThreadPriority

自分自身に GetPriorityClass / GetThreadPriorityTOP

まずは簡単な取得からやってみます。対象は自分自身です。GetPriorityClass はターゲットのプロセスの基本優先度を、GetThreadPriority はターゲットのスレッドの基本優先度を取得します。

GetPriorityClass には対象のプロセスのハンドルを渡します。で、自分自身のプロセスのハンドルはというと、GetCurrentProcess() API で得られます。この API は引数不要です。

同じように GetThreadPriority には対象のスレッドのハンドルを渡します。で、(略) GetCurrentThread() API で (略)。

また、GetPriorityClass と GetThreadPriority の戻り値は、基本優先度をあらわす定数なんですが、Delphi の標準のユニットファイルにはどっこにも(多分)定義されてないので、SDK を見ながら宣言します。

そんなこんなで、次のような感じで。

//-----------------------------------------------------------------------------
//  GetPriorityClass の戻り値
const
    ABOVE_NORMAL_PRIORITY_CLASS = $00008000;
    BELOW_NORMAL_PRIORITY_CLASS = $00004000;
    HIGH_PRIORITY_CLASS         = $00000080;
    IDLE_PRIORITY_CLASS         = $00000040;
    NORMAL_PRIORITY_CLASS       = $00000020;
    REALTIME_PRIORITY_CLASS     = $00000100;

//-----------------------------------------------------------------------------
//  GetThreadPriority の戻り値
const
    THREAD_PRIORITY_ERROR_RETURN  = MaxInt;
    THREAD_PRIORITY_ABOVE_NORMAL  =      1;
    THREAD_PRIORITY_BELOW_NORMAL  =     -1;
    THREAD_PRIORITY_HIGHEST       =      2;
    THREAD_PRIORITY_IDLE          =    -15;
    THREAD_PRIORITY_LOWEST        =     -2;
    THREAD_PRIORITY_NORMAL        =      0;
    THREAD_PRIORITY_TIME_CRITICAL =     15;

//-----------------------------------------------------------------------------
//  GetPriorityClass のテスト
procedure TForm1.Button1Click(Sender: TObject);
var
    LResult: DWORD;
    LText: String;
begin
    LResult := GetPriorityClass(GetCurrentProcess());
    if (LResult = 0) then
    begin
        LText := SysErrorMessage(GetLastError());
    end
    else
    begin
        case LResult of
        ABOVE_NORMAL_PRIORITY_CLASS : LText := 'ABOVE_NORMAL_PRIORITY_CLASS';
        BELOW_NORMAL_PRIORITY_CLASS : LText := 'BELOW_NORMAL_PRIORITY_CLASS';
        HIGH_PRIORITY_CLASS         : LText := 'HIGH_PRIORITY_CLASS';
        IDLE_PRIORITY_CLASS         : LText := 'IDLE_PRIORITY_CLASS';
        NORMAL_PRIORITY_CLASS       : LText := 'NORMAL_PRIORITY_CLASS';
        REALTIME_PRIORITY_CLASS     : LText := 'REALTIME_PRIORITY_CLASS';
        else LText := 'NORMAL_PRIORITY_CLASS';
        end;
    end;

    Label1.Caption := LText;
end;

//-----------------------------------------------------------------------------
//  GetThreadPriority のテスト
procedure TForm1.Button2Click(Sender: TObject);
var
    LResult: Integer;
    LText: String;
begin
    LResult := GetThreadPriority(GetCurrentThread());
    if (LResult = THREAD_PRIORITY_ERROR_RETURN) then
    begin
        LText := SysErrorMessage(GetLastError());
    end
    else
    begin
        case LResult of
        THREAD_PRIORITY_ABOVE_NORMAL : LText := 'THREAD_PRIORITY_ABOVE_NORMAL';
        THREAD_PRIORITY_BELOW_NORMAL : LText := 'THREAD_PRIORITY_BELOW_NORMAL';
        THREAD_PRIORITY_HIGHEST      : LText := 'THREAD_PRIORITY_HIGHEST';
        THREAD_PRIORITY_IDLE         : LText := 'THREAD_PRIORITY_IDLE';
        THREAD_PRIORITY_LOWEST       : LText := 'THREAD_PRIORITY_LOWEST';
        THREAD_PRIORITY_NORMAL       : LText := 'THREAD_PRIORITY_NORMAL';
        THREAD_PRIORITY_TIME_CRITICAL: LText := 'THREAD_PRIORITY_TIME_CRITICAL';
        else LText := 'THREAD_PRIORITY_NORMAL';
        end;
    end;

    Label2.Caption := LText;
end;

ぐだぐだ書いてますが、赤太字の部分だけです。入り口は敷居を下げていきます。実行結果もあまりにもしょうもないので、いつものようなスクリーンショットは割愛します。こういうことするの面倒になってきてるなぁ。

結果は「NORMAL_PRIORITY_CLASS」と「THREAD_PRIORITY_NORMAL」でした。やっぱり。

自分自身に SetPriorityClass / SetThreadPriorityTOP

続きをかけてうれしいです。Get をやったので次は当然 Set です。

今度は Set なので、どんな優先度に変更するかを選択しないといけない邪魔くささがあるのですが、何とか乗り越えてリストボックスで選択できるようにしました。ここでは、FormCreate でリストボックスに選択肢を作っています。

こんな感じ。

//-----------------------------------------------------------------------------
//  前準備
procedure TForm1.FormCreate(Sender: TObject);
begin
    //  SetPriorityClass のための優先度選択リスト
    LboxPriClass.Items.AddObject('ABOVE_NORMAL_PRIORITY_CLASS', TObject(ABOVE_NORMAL_PRIORITY_CLASS));
    LboxPriClass.Items.AddObject('BELOW_NORMAL_PRIORITY_CLASS', TObject(BELOW_NORMAL_PRIORITY_CLASS));
    LboxPriClass.Items.AddObject('HIGH_PRIORITY_CLASS', TObject(HIGH_PRIORITY_CLASS));
    LboxPriClass.Items.AddObject('IDLE_PRIORITY_CLASS', TObject(IDLE_PRIORITY_CLASS));
    LboxPriClass.Items.AddObject('NORMAL_PRIORITY_CLASS', TObject(NORMAL_PRIORITY_CLASS));
    LboxPriClass.Items.AddObject('REALTIME_PRIORITY_CLASS', TObject(REALTIME_PRIORITY_CLASS));
    LboxPriClass.ItemIndex := 4;

    //  SetThreadPriority のための優先度選択リスト
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_ABOVE_NORMAL', TObject(THREAD_PRIORITY_ABOVE_NORMAL));
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_BELOW_NORMAL', TObject(THREAD_PRIORITY_BELOW_NORMAL));
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_HIGHEST', TObject(THREAD_PRIORITY_HIGHEST));
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_IDLE', TObject(THREAD_PRIORITY_IDLE));
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_LOWEST', TObject(THREAD_PRIORITY_LOWEST));
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_NORMAL', TObject(THREAD_PRIORITY_NORMAL));
    LboxThreadPri.Items.AddObject('THREAD_PRIORITY_TIME_CRITICAL', TObject(THREAD_PRIORITY_TIME_CRITICAL));
    LboxThreadPri.ItemIndex := 5;
end;

//-----------------------------------------------------------------------------
//  SetPriorityClass のテスト
procedure TForm1.Button3Click(Sender: TObject);
var
    LSetPri: DWORD;
    //LResult: BOOL;
    LText: String;
begin
    LSetPri := DWORD(LboxPriClass.Items.Objects[LboxPriClass.ItemIndex]);
    {LResult := }SetPriorityClass(GetCurrentProcess(), LSetPri);
    LText := SysErrorMessage(GetLastError());
    Label3.Caption := LText;
end;

//-----------------------------------------------------------------------------
//  SetThreadPriority のテスト
procedure TForm1.Button4Click(Sender: TObject);
var
    LSetPri: DWORD;
    //LResult: BOOL;
    LText: String;
begin
    LSetPri := DWORD(LboxThreadPri.Items.Objects[LboxThreadPri.ItemIndex]);
    {LResult := }SetThreadPriority(GetCurrentThread(), LSetPri);
    LText := SysErrorMessage(GetLastError());
    Label4.Caption := LText;
end;

テストに使ったプログラムのスクリーンショットです。4つのボタンを順番に押していったところです。

ホンマか?というわけで、念のためスレッドの優先度までは確認できないですがタスクマネージャでも確認してみます。確かにそうなってます。ひとつだけ「リアルタイム」の文字が光っています。

「基本」優先度というだけあって、Windows のなんとかいうスケジューラに優先度を高くしてもらいやすいというだけのようです。10秒間で何回割り算できるか?といった何かの処理を繰り返してみて、基本優先度ごとに比較してみるのも面白そうです。

スレッドの優先度とプロセスの優先度をそれぞれ設定できるとしても、人のプログラムのどのスレッドの優先度をあげたらよいのかを指定するのは操作的に困難な気がします。となると特定のプロセスの基本優先度をあげるだけでそれなりの速度向上を体感できるなら、SetThreadPriority までは考えないでおこうとすることもできるわけだし。

とにもかくにも自分以外のプロセスやスレッドを列挙するのがかなり面倒なので、やる気をあげるためのカタパルト代わりに、基本優先度別に、10秒間で何かの処理を何回(?)できるかを試してみるのは重要な気がしてきました。

EOFTOP