WideStudio/MWT Logo
WideStudio/MWT
Programming Guide
WideStudio/MWT Index
目次


スレッドクラスとワーキングダイアログによる長時間の処理の実行



スレッドクラスとワーキングダイアログによる長時間の処理の実行

WSCvthread クラスと WSCworkingDialog を利用すると、 処理時間の長い処理を実行中に描画を止めることなく行なうことができます。

ここでは簡単な例を示しながら、 スレッドとワーキングダイアログの実装方法に関して説明を行ないます。 プッシュボタンを押下すると、 時間のかかる処理をサブスレッド上で実行し、ワーキングダイアログを 表示するようなアプリケーションを作成します。

まず、ウィンドウをひとつ用意し、プッシュボタンを配置し、 そして、WSCworkingDialog と WSCvthread クラスのインスタンスを それぞれ配置し、名称をそれぞれ、newwork_001、newvthr_002 とします。

プッシュボタンに次のようなイベントプロシージャ btnop() を設定し、 時間のかかる処理をサブスレッド上で実行し、ワーキングダイアログを 表示します。プログラム中に、存在するフラグ dialog_vis_status は、 ワーキングダイアログの popup() メソッドによる表示が終了したことを 処理中のサブスレッドに伝えるためのものです。 ワーキングダイアログがキャンセルされた場合など、popup() が復帰した後、 フラグを False に設定することで、 サブスレッドにおいてワーキングダイアログが非表示状態になったことが解ります。

#include <WScom.h>
#include <WSCfunctionList.h>
#include <WSCbase.h>
//----------------------------------------------------------
//Function for the event procedure
//----------------------------------------------------------
#include <newwin000.h>
//ワーキングダイアログが表示されているかどうかを示すフラグ
WSCbool dialog_vis_status = False;

void btnop(WSCbase* object){
  //do something...
  dialog_vis_status = True; //スレッドを生成する前にフラグをたてる
  //スレッドを生成し、処理を実行する。
  newvthr_002->executeThread();
  //ダイアログを表示状態にする。
  newwork_001->popup();     //(注意)ダイアログが非表示状態になるまで復帰せず。
  dialog_vis_status = False;
}
static WSCfunctionRegister  op("btnop",(void*)btnop);

次に、WSCvthread クラスのインスタンス newvthr_002 に対して、 サブスレッドとして実行する処理を記述したイベントプロシージャを THREAD-STARTED トリガで設定します。 ワーキングダイアログ等でいつでもキャンセルできるようにするため、 サブスレッドとして実行するイベントプロシージャの記述で重要な点のひとつは、 長時間かかる処理をみじかく区切って一定量づつ処理を実行する点です。 下記に示す例は、長い処理全体を 100 回に区切って実行し、 変数 cnt でカウントします。 そして、そのカウントをそのままワーキングダイアログの進み具合の表示に 利用しています。

#include <WScom.h>
#include <WSCfunctionList.h>
#include <WSCbase.h>
#include <unistd.h>
//----------------------------------------------------------
//Function for the event procedure
//----------------------------------------------------------
#include <newwin000.h>
extern long cnt;
extern WSCbool dialog_vis_status;
void thread_proc(WSCbase* object){
  cnt=0;
  while(1){
    //処理の進み具合をしめすカウンタをカウントアップします。
    cnt++;
    //カウンタの値をワーキングダイアログに反映させるため、
    //メインスレッド上で ACTIVATE トリガのイベントプロシージャを実行します。
    newvthr_002->sendActivateEvent();

    if (dialog_vis_status == False){
      //ダイアログが非表示すなわちキャンセルされたならば処理を終了します。
      return;
    }
    if (cnt > 100){
      //みじかく区切った処理を100回行なったならば処理を終了します。
      return;
    }

    //ここで長時間かかる処理をみじかく区切って一定量づつ実行します。
#ifdef MSW
    Sleep(1000);
#else
    sleep(1);
#endif
  }
}
static WSCfunctionRegister  op("thread_proc",(void*)thread_proc);

インスタンスは基本的にスレッドアンセーフなため、 ワーキングダイアログの表示に対して カウンタ値を反映させるために、 sendActivateEvent() メソッドを使用して、メインスレッド上で ACTIVATE によるイベントプロシージャを起動し、そこでワーキングダイアログ にアクセスするようにします。

#include <WScom.h>
#include <WSCfunctionList.h>
#include <WSCbase.h>
//----------------------------------------------------------
//Function for the event procedure
//----------------------------------------------------------
#include <newwin000.h>
long cnt = 0;
void act_ep(WSCbase* object){
  //進み具合をしめすカウンタ値をプロパティに設定します。
  newwork_001->setProperty(WSNvalue,cnt);

  //カウンタ値が 100 以上となった場合、ダイアログを非表示とし、
  //処理の終了とします。
  if (cnt>100){
    newwork_001->setVisible(False);
  }
}
static WSCfunctionRegister  op("act_ep",(void*)act_ep);



ロースレッドクラスとワーキングダイアログによる長時間の処理の実行

WSDthread クラスと WSCworkingDialog を利用した、 処理時間の長い処理を実行する例を示します。

ウィンドウをひとつ用意し、プッシュボタンを配置します。 そして、WSCworkingDialog クラスのインスタンスを配置し、名称を newwork_000 とします。

プッシュボタンに次のようなイベントプロシージャ btnop() を設定し、 時間のかかる処理をサブスレッド上で実行し、ワーキングダイアログを 表示します。

存在するフラグ canceled を使用した、 安全にサブスレッドをキャンセルする方法、 WSDthread::terminateThread() メソッドを 利用した強制的なサブスレッドの停止方法を示します。 WSDthread::terminateThread() メソッドによるサブスレッドの停止は、 処理途中で強制的に停止させられるため、ファイル資源の操作等の 資源操作処理には向きません。



サブスレッドを強制終了する例です。

#include <WScom.h>
#include <WSCfunctionList.h>
#include <WSCbase.h>
#include <WSDthread.h>
#include <stdlib.h>
#include <unistd.h>
//----------------------------------------------------------
//Function for the event procedure
//----------------------------------------------------------
#include <newwin000.h>
WSDthread* thr = NULL;
WSCbool canceled = False;

//サブスレッドとして動作するプロシージャ
void* thread_func(WSDthread* obj,void*){
  //カウンタ
  long cnt= 0;
  while(1){
    //処理の進み具合をしめすカウンタをカウントアップします。
    cnt++;
    //カウンタの値をワーキングダイアログに反映させるため、
    //メインスレッド上でプロシージャを実行します。
    obj->execCallback((void*)cnt);


    //ここで長時間かかる処理をみじかく区切って一定量づつ実行します。
#ifdef MSW
    Sleep(1000);
#else
    sleep(1);
#endif

    //カウンタが100になった場合、処理を終了します。
    if (cnt == 100){
      return NULL;
    }
  }
  return NULL;
}

//カウンタ値をワーキングダイアログに反映させるためのプロシージャ
//WSDthread::execCallback() メソッドによってメインスレッドで実行される。
void callback_func(WSDthread*,void* val){
  long cnt = (long)val;
  //カウンタ値をワーキングダイアログに反映
  newwork_000->setProperty(WSNvalue,cnt);
  if (cnt == 100){
    newwork_000->setVisible(False);
  }
}

//ボタン押下により、ワーキングダイアログを表示し、処理を開始。
void btnop(WSCbase* object){
  if (thr == NULL){
    //スレッドインスタンスを生成。
    thr = WSDthread::getNewInstance();
    //サブスレッドとして実行するプロシージャを設定
    thr->setFunction(thread_func);
    //サブスレッドから呼び出される
    //メインスレッド上のコールバックプロシージャを設定
    thr->setCallbackFunction(callback_func);
    //サブスレッドを生成
    thr->createThread(NULL);
    //ワーキングダイアログを表示
    long val = newwork_000->popup();
    if (val == WS_DIALOG_OK){
    }else{
      //サブスレッドを強制終了する場合。
      thr->terminateThread();
    }
  }else{
    exit(0);
  }
}
static WSCfunctionRegister  op("btnop",(void*)btnop);

サブスレッドをフラグを参照して安全に終了する例です。

#include <WScom.h>
#include <WSCfunctionList.h>
#include <WSCbase.h>
#include <WSDthread.h>
#include <stdlib.h>
#include <unistd.h>
//----------------------------------------------------------
//Function for the event procedure
//----------------------------------------------------------
#include <newwin000.h>
WSDthread* thr = NULL;
WSCbool canceled = False;

//サブスレッドとして動作するプロシージャ
void* thread_func(WSDthread* obj,void*){
  //カウンタ
  long cnt= 0;
  while(1){
    //処理の進み具合をしめすカウンタをカウントアップします。
    cnt++;
    //カウンタの値をワーキングダイアログに反映させるため、
    //メインスレッド上でプロシージャを実行します。
    obj->execCallback((void*)cnt);

    //ここで長時間かかる処理をみじかく区切って一定量づつ実行します。
#ifdef MSW
    Sleep(1000);
#else
    sleep(1);
#endif

    //カウンタが100になった場合、処理を終了します。
    if (cnt == 100){
      return NULL;
    }
    //フラグを参照し、処理を中断すべきかを判断します。
    if (canceled != False){
      return NULL;
    }
  }
  return NULL;
}

//カウンタ値をワーキングダイアログに反映させるためのプロシージャ
//WSDthread::execCallback() メソッドによってメインスレッドで実行される。
void callback_func(WSDthread*,void* val){
  long cnt = (long)val;
  //カウンタ値をワーキングダイアログに反映
  newwork_000->setProperty(WSNvalue,cnt);
  if (cnt == 100){
    newwork_000->setVisible(False);
  }
}

//ボタン押下により、ワーキングダイアログを表示し、処理を開始。
void btnop(WSCbase* object){
  if (thr == NULL){
    //スレッドインスタンスを生成。
    thr = WSDthread::getNewInstance();
    //サブスレッドとして実行するプロシージャを設定
    thr->setFunction(thread_func);
    //サブスレッドから呼び出される
    //メインスレッド上のコールバックプロシージャを設定
    thr->setCallbackFunction(callback_func);
    //サブスレッドを生成
    thr->createThread(NULL);
    //ワーキングダイアログを表示
    long val = newwork_000->popup();
    if (val == WS_DIALOG_OK){
    }else{
      //サブスレッドに処理を中止させます。
      canceled = True;
    }
  }else{
    exit(0);
  }
}
static WSCfunctionRegister  op("btnop",(void*)btnop);


Document Release 3.90 for WideStudio/MWT ver 3.90, Jul 2005


WideStudio/MWT documents index | 目次

Copyright(C) WideStudio/MWT Development Team, 1999-2005 Last modified: Jul 31, 2005