#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のトップページをご覧ください。