#pragma twice

KAB-studio > プログラミング > #pragma twice > 296 Version 14.29 別スレッドで検索!

#pragma twice 296 Version 14.29 別スレッドで検索!

前のページへ 表紙・目次へ 次のページへ

 Version 14.29
別スレッドで検索!

「さて、前回のプログラムをたとえば」

    iCount = CountMatchFile( "C:\\", "readme.txt" );

「というふうに C ドライブ全体で検索すると、結構時間が掛かると思いま
す」
『しかもその間、アプリ動かない……これがつまり、検索処理してるから、
ウィンドウを操作してもメッセージキューに貯まるだけで何も処理されな
い、って状態なんだね』
「そういうこと。そこで!」
『マルチスレッドの出番!』
「というわけです。でもここから一筋縄ではいかないから」
『う……』
「まず、マルチスレッドは Version 14.14 ( No.281 ) と同じく 
_beginthread() を使用します。この時と同じく StdAfx.h にヘッダーを追
加します」

#include <process.h> // 追加。

//{{AFX_INSERT_LOCATION}}

「〈//{{AFX_INSERT_LOCATION}}〉の上に追加してください」
『ほい』
「では使ってみます」

/*
    指定したフォルダからファイルを検索します。
    戻り値として一致数を返します。
 */
int CountMatchFile
    ( const char * const p_pchFolderPath
    , const char * const p_pchFileName 
    )
{
    int iNum = 0;

    // 検索するフォルダをカレントディレクトリにします。
    BOOL bRes;
    bRes = SetCurrentDirectory( p_pchFolderPath );
    if( bRes == FALSE )
    {
        // フォルダが存在しません。
        return -1;
    }

    CStringArray cFolderStrAry;

    // 最初のファイルを取得します。
    WIN32_FIND_DATA stWin32FindData;
    HANDLE hHandle = NULL;
    hHandle = FindFirstFile( "*", &stWin32FindData );
    do
    {
        if( stWin32FindData.dwFileAttributes 
                & FILE_ATTRIBUTE_DIRECTORY )
        {
            // フォルダなので取っておきます。
            cFolderStrAry.Add( stWin32FindData.cFileName );
        }
        else if( _stricmp
                ( stWin32FindData.cFileName
                , p_pchFileName 
                ) == 0 )
        {
            // ファイル名が一致しました。
            ++iNum;
        }

        // 次のファイルを取得します。
    }while( FindNextFile( hHandle, &stWin32FindData ) );

    // ハンドルを閉じます。
    FindClose( hHandle );

    // フォルダに対して再帰呼び出しをします。
    for( int iF1 = 0; iF1 < cFolderStrAry.GetSize(); ++iF1 )
    {
        if  (
            ( cFolderStrAry.GetAt( iF1 ) == "." ) ||
            ( cFolderStrAry.GetAt( iF1 ) == ".." )
            )
        {
            // . と .. はスキップします。
            continue;
        }

        // フォルダを連結します。
        CString cPathStr = p_pchFolderPath;
        if  (
            ( cPathStr.GetAt
                ( cPathStr.GetLength() - 1 ) != '\\' ) ||
            (
                ( cPathStr.GetAt
                    ( cPathStr.GetLength() - 1 ) == '\\' ) &&
                ( _mbsbtype
                    ( (const unsigned char *)(LPCTSTR)cPathStr
                    , cPathStr.GetLength() - 1 
                    ) == 2 )
            )
            )
        {
            // 最後に \ がなければくっつけます。
            cPathStr += "\\";
        }
        cPathStr += cFolderStrAry.GetAt( iF1 );
        // 再帰呼び出しします。
        iNum += CountMatchFile( cPathStr, p_pchFileName );
    }

    return iNum;
}

void StartCountMatchFile( void *p_p )
{
    int iCount = 0;
    iCount = CountMatchFile( "C:\\", "readme.txt" );
    TRACE( "一致数: %d\n", iCount );
}

void CSearchDlgDlg::OnSearchStart() 
{
    HANDLE hThread;
    hThread
        = (HANDLE)_beginthread( StartCountMatchFile, 0, NULL );

    // 【検索中】ダイアログを表示します。
    CSearchingDlg cDlg;
    cDlg.DoModal();
}

『長! って、 CountMatchFile() ってこの前と同じっぽいけど』
「同じなんだけど……ほら、この前プログラム間違えたから、これが正解版
ってことで……」
『あー……』
「というわけで CountMatchFile() の解説は前回と前々回を参照。ここでは
マルチスレッドの部分を解説します。まずは別スレッドで呼び出す部分」

    HANDLE hThread;
    hThread
        = (HANDLE)_beginthread( StartCountMatchFile, 0, NULL );

「 _beginthread() で、別スレッドで StartCountMatchFile() を呼び出し
ます」

void StartCountMatchFile( void *p_p )
{
    int iCount = 0;
    iCount = CountMatchFile( "C:\\", "readme.txt" );
    TRACE( "一致数: %d\n", iCount );
}

『こっちがこの前呼んでた方だね』
「ここは同じ。だから、検索部分そのまままるごと別スレッドで呼び出した
ことになります」
『おー』
「で、それとは別に、メインスレッドではダイアログを表示します」

    // 【検索中】ダイアログを表示します。
    CSearchingDlg cDlg;
    cDlg.DoModal();

『 Version 14.26 ( No.293 ) の時に作ったやつだね』
「これを実行してみて」
『ほい、実行っと。【検索開始】ボタン押して〜おっ、【検索中】ダイアロ
グが出た』
「まだ【キャンセル】ボタンは機能しないけどね」
『う、そうだ……』
「でも押せるでしょ」
『あ、押せるし、ダイアログも動くし』
「これがマルチスレッドの効果」
『そっか、検索は別スレッドだから、メッセージループが止まらないんだ
ね』
「そういうこと。で、少し待つと」
『あ、デバッグウィンドウに一致数出た』
「この流れを図にしてみます」

OnSearchStart()                           StartCountMatchFile()
呼び出し→→→→→→→→→→→→→→→→→別スレッドで開始
【検索中】ダイアログ表示                  検索開始
...                                       (検索中...)
...                                       検索終了。
(ダイアログを閉じたり                    StartCountMatchFile() 終了
ウィンドウを動かしたり                    (スレッドもここで終了)
できます)                    
【ファイル検索】ダイアログ閉じます。
(アプリケーション終了)

『別々に分かれて、あとでくっつくことはないわけね』
「そういうこと。マルチスレッドの場合、スレッド間の協調が難しいから、
こういうふうに〈処理を投げっぱなしにする〉のが簡単な方法」
『検索処理を投げっぱなしにするわけね』
「そういうこと。でも、実際には協調が必要。今の段階でまだ実装してない
機能は」

・検索対象フォルダの表示
・検索結果の表示
・キャンセル機能
・検索終了時にキャンセルダイアログを閉じる機能

『うわ、かなりある!』
「まだまだ道は険しいからねー」

/*
    Preview Next Story!
*/
『でもさでもさ、なんかスレッド使うだけで結構ちゃんとした感じ!』
「こういうのって楽しいでしょ」
『う”、そ、そうだけど……』
「次はもっと楽しくなるよ」
『え!?』
「というわけで次回」
< Version 14.30 スレッドを途中で止める >
『につづく!』
「こうやって機能がどんどん追加できると楽しくなるよー?」
『……なんかあたしのこといじってない?』
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。