SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Windowsアプリケーションで「処理中」を表現する

時間のかかる処理で「処理中」を表現する(後編)

Windowsアプリケーションで処理中を表現する様々な方法

  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード WaitSample_2.zip (137.4 KB)

並列ライブラリを利用する

 マルチスレッド版にしたことでメッセージ処理が滞ることがなくなり、ユーザー操作のレスポンスが今までと違い格段によくなっていることが分かると思います。ここまで来ると、気になるのがCPU利用率です。ここまでのプログラムはアクティブに処理する部分が1つしかないため、結果的にCPUパワーは1つ分しか利用していません(サンプルプログラムはグラフに分かりやすく出るようにわざと、CPUの利用を1か所に寄せています)。現在は多くのマシンが2~4個のCPUコアを持っています。時間のかかる処理も、複数のコアで同時に行うようにすれば、全力で作業できます。

 Visual Studio 2010では、同時実行ライブラリの中のPPL(Parallel Pattern Library:並列パターンライブラリ)に、ループを並列化するなどさまざまな並列化ルーチンが用意されています。今回はこの中から、parallel_forというforループを並列化するロジックを利用してマルチコアで全力で作業するようにしてみました。また、分かりやすいようにダイアログを出している間の時間を計測して、どの程度で処理が終わっているかも分かるようにしてあります。

PPL利用版
void _cdecl BusyLoopThProcDlgPPL( void* param )
{
  CThreadParamDlg* pParam = static_cast( param );
  int nSec = pParam->m_workTime/1000;
  Concurrency::parallel_for( 0, nSec, []( int ){
    DWORD dwStart = GetTickCount();
    while( (GetTickCount()-dwStart) < 1000 );
  });
  //  端数はおまけ処理として扱う(サンプルではここは通らない)
  DWORD restTime = pParam->m_workTime%1000;
  if( restTime != 0 ){
    DWORD dwStart = GetTickCount();
    while( (GetTickCount()-dwStart) < restTime );
  }
  PostMessage( pParam->m_hwndDlg, WM_COMMAND, MAKEWPARAM( IDOK, 0 ), 0 );  //  処理終了はOKメニュー風に通知
}
INT_PTR CALLBACK DlgProc_PPL(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch( message ){
    case WM_INITDIALOG:
      {
        CSimpleWaitCursor  wait;
        CThreadParamDlg*  pParam = reinterpret_cast( lParam );
        pParam->m_hwndDlg = hDlg;
        Concurrency::CurrentScheduler::ScheduleTask( BusyLoopThProcDlgPPL, pParam );
      }
      return TRUE;
    case WM_COMMAND:
      if( LOWORD(wParam) == IDOK ){
        EndDialog( hDlg, LOWORD(wParam) );
        return TRUE;
      }
      break;
  }
  return FALSE;
}
void ThreadBusyLoopModalPPL( HWND hwnd, DWORD dwTime )
{
  DWORD dwStart = GetTickCount();
  {
    CThreadParamDlg  param( dwTime );
    DialogBoxParam( hInst, MAKEINTRESOURCE(IDD_WAIT), hwnd, DlgProc_PPL, reinterpret_cast<LPARAM>( &param ) );
  }
  DWORD dwEnd = GetTickCount();
  TCHAR  szBuff[256];
  wsprintf( szBuff, _T("経過時間:%u.%03u 秒"), (dwEnd-dwStart)/1000, (dwEnd-dwStart)%1000 );
  MessageBox( hwnd, szBuff, _T("WaitSample"), MB_OK );
}

 サンプルは30秒処理するようにしてあります。手元の開発環境が8コアだったので計測したところ、4~5秒程度で終了していました。8等分より少し時間がかかっていますが、スレッド切り替えのオーバーヘッドを考慮すれば、処理時間としては悪くないと思われます。

おわりに

 前編、後編にわたって、いくつかの「処理中」を表現する方法を紹介してきました。これですべてではありませんが、基本となる部分は一通り網羅していると思います。マルチスレッドも安易に利用できるようなものではありませんが、ハードウェアの能力を最大限活用するためには、避けては通れない時代になっています。CodeZineにもマルチスレッド(並列処理)の記事がたくさんあるので、参考にしていただければと思います。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Windowsアプリケーションで「処理中」を表現する連載記事一覧
この記事の著者

とっちゃん(トッチャン)

Microsoft MVP for Development Tools Visual C++Windows Installer 系を中心にオンライン/オフラインで活動しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5352 2010/08/05 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング