2011年5月25日水曜日

しばらくお待ちください。

Windowsアプリケーションに限らず、重たい処理や時間のかかる処理を実行させる際、利用者にストレスを感じさせないように、『Now Loading』『しばらくお待ちください。』的な画像を表示させることがよくある。

砂時計やプログレスバー、クルクル回る画像等々、単純にアニメーションGIF形式の画像ファイルを表示していることが多い。

(画像ファイルの素材は"Loading"で検索すればいっぱい出てくる ⇒ こんな感じ


現在取り組んでいる案件においても、この『しばらくお待ちください。』処理を取り入れることになった。

単純に Form 上に PictureBox を張り付けて、Image プロパティにアニメーションGIFを設定し、この Form を単体で表示(Show)させると、期待通りの動きをした。

よしよし。

実際の重たい処理を行う直前でこの Form を表示(Show)し、処理の直後で非表示(Close)してみた。

ん?

Form は表示されるが、アニメーションGIFが動かない・・・。
処理の継続中は制御が戻らないからアニメーションGIFが動かない・・・。

で、

重たい処理の所々に、

System.Windows.Forms.Application.DoEvents();

を加えてみる。

動いた。でも・・・あれ?・・・。ぎこちない・・・。重たい処理がいっそう遅くなった気がする。

よくよく考えてみたら、同一スレッド内で重たい処理とアニメーションGIFの表示処理を行っているのだから、DoEvents でアニメーションGIFの表示処理に制御が戻っている分、重たい処理が遅くなってしまっているのだ。


ってことで、

アニメーションGIFの表示を別スレッドで行ってみることにした。
具体的には、以下のような実装になります。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//別スレッド用メンバ変数を用意
Thread m_nowLoading = null;

・・・

//コンストラクタ内で変数を初期化
m_nowLoading = new Thread(new ThreadStart(NowLoadingProc));

m_nowLoading.IsBackground = true;

・・・

//アニメーションGIFを張り付けた Form (frmLoading)の表示処理
private void NowLoadingProc()
{
    frmLoading frmLoad = new frmLoading();
    try
    {
        frmLoad.ShowDialog();
        frmLoad.Dispose();
    }
    catch(ThreadAbortException)
    {
        frmLoad.Close();
    }
}


・・・

//重たい処理の直前でスレッドを開始
m_nowLoading.Start();

<重たい処理>

//重たい処理の直後でスレッドを終了
m_nowLoading.Abort();

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Form の TopMost プロパティは true にしてます。
表示させる位置の調整のための処理や、スレッドを終了(Abort)した後、再度呼び出す際のスレッドの初期化処理は省略しています。

以上

0 件のコメント:

コメントを投稿