C#のWinformsでuseWaitCursorが戻らないバグ

今回私がハマったのは、C#のWinFormsでuseWaitCursorを使ったあとに元のカーソルに戻らない!というバグ。

たぶんこれ、WinFormsのバグですよ。

っていうのもね。下記のようなコードを書いたわけです。

try{

this.UseWaitCursor = true;
// 時間のかかるイベント。非同期実装
MessageBox.Show("処理が終わりました。")

}catch(Exception exception){

MessageBox.Show("エラーが発生しました。")

}finally{

this.UseWaitCursor = false;

}

ありがちなコードですね。

処理に時間がかかるから、非同期実装して、その前後にUseWaitCursorを置く。

めちゃくちゃシンプルです。

私の場合、try catch finallyを仕掛けて途中でエラーが出ても戻るようにしています。

なのに!!

なのに!!!

数回に1回待機中からもとに戻らんことがある!!!

っということで、UseWaitCursorから戻らないときに内部的にどのようなステータスを持っているのか見てみました。

目次

Cursorに関係するプロパティ

まずはCursorに関するプロパティはどこにあるのか?ということですが、下記の通りです。

  • Control.Cursor
  • Control.UseWaitCursor
  • Application.UseWaitCursor
  • Cursor.Current

続いて、この事象が発生した時のすべてのプロパティを見ていきます。

MessageBox.Show(Cursor.Current.ToString());

適当なボタンに上記のプログラムを仕込んで、事象が発生したらボタンを押して、中身を見るようにします。

  • Cursor.CurrentはDefaultになってる。

続いてApplication.UseWaitCursorを見てみる。

実行前はこんな感じ。

事象が発生している状態はこんな感じ。

続いて各コントロールのUseWaitCursorのプロパティを見てみる。

MessageBox.Show(GetWaitCursorStatus(this));

これを仕込んで、GetWaitCursorStatusは下記の関数を作った。

        private string GetWaitCursorStatus(Control control)
        {
            var str = $@"{control.Name} : {control.UseWaitCursor.ToString()}";

            foreach (Control c in control.Controls)
            {
                str += Environment.NewLine + GetWaitCursorStatus(c);
            }

            return str;
        }

コントロールの中にあるコントロールを再帰的に取得して、中身を見てくだけの関数。

事象が発生する前はこんな感じ。

全部Falseになってる。

事象が発生した時のプロパティはこんな感じ。

うん。

変わりないね。

っで、最後のControl.Cursorを見てみる。

        private string GetWaitCursorStatus(Control control)
        {
            var str = $@"{control.Name} : {control.Cursor.ToString()}";

            foreach (Control c in control.Controls)
            {
                str += Environment.NewLine + GetWaitCursorStatus(c);
            }

            return str;
        }

さっきのコードをちょっと修正して実行。

まあ普通って感じですね。

事象発生してるときはこんな感じ。

はい見つけました。

Control.CursorがWaitCursorになっててもとに戻ってない!!!!

ということでバグが発生しているコードに、下記を追加してFix!!

dgv_MainGrid.Cursor = Cursor.Current;
try{

this.UseWaitCursor = true;
// 時間のかかるイベント。非同期実装
MessageBox.Show("処理が終わりました。")

}catch(Exception exception){

MessageBox.Show("エラーが発生しました。")

}finally{

this.UseWaitCursor = false;
dgv_MainGrid.Cursor = Cursor.Current;
}

この記事が気に入ったら
いいねしてね!

どんどんシェア待ってるぜ!!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次