2

プロセスの進行中に進行状況バーを表示しようとしています...私のアプリケーションでは、ファイルを読み取って操作する必要がある状況があります(完了するまでに時間がかかります)..進行状況バーを表示したいこの操作中..私が呼び出している特定の関数はwin 32です...したがって、以下のコードを確認すると、ダイアログウィンドウに進行状況バーを作成し、スレッドを作成するところまで来ています。投稿する方法がわかりませんメッセージとメッセージとハンドルを取得する場所...助けてください..事前に感謝します

    //my  function
    int Myfunction(....)
    {
     MSG msg;
     HWND dialog = CreateWindowEx(0,WC_DIALOG,L"Proccessing...",WS_OVERLAPPEDWINDOW|WS_VISIBLE,
         600,300,280,120,NULL,NULL,NULL,NULL);
     HWND pBar =  CreateWindowEx(NULL,PROGRESS_CLASS,NULL,WS_CHILD|WS_VISIBLE,40,20,200, 20,
           dialog,(HMENU)IDD_PROGRESS,NULL,NULL);


      while(GetMessage(&msg,NULL,0,0))
{
    TranslateMessage(&msg);
     Dispatch(&message);
}
SendMessage(pBar,PBM_SETRANGE,0,MAKELPARAM(0,noOfFile));

     HANDLE getHandle = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)SetFilesForOperation(...),
        NULL,NULL,0);

    }


    LPARAM SetFilesForOperation(...)       
    {

     for(int index = 0;index < noOfFiles; index++)
     {


      *checkstate = *(checkState + index);
      if(*checkstate == -1)
      {
       *(getFiles+i) = new TCHAR[MAX_PATH];
       wcscpy(*(getFiles+i),*(dataFiles +index));
       i++;

      }
      else
      {
       (*tempDataFiles)->Add(*(dataFiles+index));
       *(checkState + localIndex) = *(checkState + index);
       localIndex++;
      }

      PostMessage(pBar,PBM_SETPOS,(WPARAM)index,0);
     }
    }

EDIT2: AFXTHREAD の使用

//instead of createthread i used AfxBegin thread
    ptrThread = AfxBeginThread((AFX_THREADPROC)SetFilesForOperation(pBar,checkstate,checkState,noOfFiles,i,getFilesforcompression,dataFiles,&tempDataFiles,localIndex),
        NULL,THREAD_PRIORITY_ABOVE_NORMAL,NULL,NULL,NULL);


for(int index = 0;index < noOfFiles; index++)
    {

        MSG msg;
        *checkstate = *(checkState + index);
        if(*checkstate == -1)
        {
            *(getFilesforcompression+i) = new TCHAR[MAX_PATH];
            //*(getFilesforcompression+i) = L"C:\\Documents and Settings\\rakesh\\Desktop\\try2_Extracted";
            wcscpy(*(getFilesforcompression+i),*(dataFiles +index));
            i++;

        }
        else
        {
            (*tempDataFiles)->Add(*(dataFiles+index));
            *(checkState + localIndex) = *(checkState + index);
            localIndex++;
        }


        //PostMessage( pBar, PBM_SETPOS, (WPARAM)index, 0 );
        PostMessage( pBar, PBM_SETRANGE, 0, MAKELPARAM( 0, noOfFiles ) );
        //PostMessage( pBar, PBM_SETPOS, (WPARAM)index, 0 );
        PostMessage( pBar, PBM_STEPIT, (WPARAM)index, 0 );
        PostMessage( pBar, MSG_PROGRESS_VALUE, 0, 0 );


        while(1)
        {
            while(PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE))
            {


                AfxGetThread()->PumpMessage();
                Sleep(10);




        }
4

2 に答える 2

3

スレッド間でメッセージを送信する場合、いくつかの落とし穴があります。スレッドAからスレッドBにメッセージを送信すると、内部で発生するのは、スレッドAがメッセージをスレッドBのメッセージキューに投稿することです。次に、メッセージが処理されるのを待ってから、結果をスレッドAに送り返します。これは、スレッドBでメッセージをポンピングする必要があることを意味します。そうしないと、スレッドAがデッドロックします。

特定の問題については、プログレスバーを作成した後、次のコードを入力するだけです。

SendMessage( pBar, PBM_SETRANGE, 0, MAKELPARAM( 0, noOfFiles ) );

次に、pBarをスレッドに渡す必要があります。これはとても簡単です。CreateThreadを使用すると、パラメータをvoid*としてスレッド関数に渡すことができます。したがって、CreateThreadを次のように書き直します。

HANDLE getHandle = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)SetFilesForOperation(...),
                                (void*)pBar,NULL,0);

次に、SetFilesForOperationプロトタイプを次のように変更します。

LPARAM SetFilesForOperation( HWND pBar );

スレッド関数を正しい形式にキャストすることに注意してください。したがって、Windowsは、内部的にはvoid*を渡すだけです。その後、暗黙のキャストが発生し、もう一方の端に表示されるのは、ボイド*ではなくHWNDです。構造体へのポインタをスレッド関数に渡すことで、より多くのデータを渡すことができます。SetFilesForOperationが必要な情報を取得する前に、構造体を(スコープから外すか、明示的に)解放しないように注意してください。これは、スレッド関数が後続のデータを取得すると発生する単純なイベントを使用して解決できます。その後、イベントが発生するのを作成するスレッドで待機します。

次に、ループの最後に次のメッセージを追加するだけです。

PostMessage( pBar, PBM_SETPOS, (WPARAM)index, 0 );

これにより、ループごとに1つずつバーが進みます。

編集:コメントで指摘されているように、メッセージがUIスレッドのメッセージキューに単に投稿されることを意味するリターンを待たないので、PostMessageを使用するだけの価値があります。ただし、そのメッセージキューをポンプしないと、メッセージが送信され、メッセージがキューにバックアップされるため、進行状況バーが更新されないことに注意してください。

編集2:メッセージループの後にプログレスバーの範囲を設定しています。したがって、範囲が設定されることはありません。あなたは前もってそれをする必要があります。また、メッセージポンプは、WM_QUITメッセージを送信したときにのみ終了することにも注意してください。これは理想的ではありません。ただし、スレッドループの最後に独自のメッセージを投稿することもできます。必要な変更は次のとおりです。まず、カスタム(ユーザー)メッセージを宣言する必要があります。

#define WM_EXITTHREAD WM_USER + 1

次に、メッセージループを次のように変更します。

SendMessage(pBar,PBM_SETRANGE,0,MAKELPARAM(0,noOfFile));

MSG msg;
while(GetMessage(&msg,NULL,0,0))
{ 
    if ( msg.message == WM_EXITTHREAD )
    {
         break;
    }
    TranslateMessage(&msg); 
    Dispatch(&msg); 
}

そして最後に、スレッドの最後に次のようにします。

PostMessage( pBar, WM_EXITTHREAD, 0, 0 );
EndThread( 0 );  // This is the preferred way of exiting a thread in C
return 0; // This is the preferred way of exiting a thread in C++ so that destructors get called.

Edit3:このようなピークメッセージループを使用するとどうなりますか?

while( 1 )
{
    MSG msg;
    if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
        if ( msg.message == WM_EXITTHREAD )
        {
            break;
        }
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    else
    {
        Sleep( 0 );
    }
}
于 2010-03-31T10:46:03.873 に答える
0

スレッド呼び出しで Postmessage を変更したところ、うまくいきました...

while(PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE))
                {


                    AfxGetThread()->PumpMessage();
                    Sleep(10);
}
于 2010-04-02T11:52:22.010 に答える