- PR -

ボタン押下処理中の誤作動について

1
投稿者投稿内容
しみこ
会議室デビュー日: 2004/11/17
投稿数: 3
投稿日時: 2004-11-17 18:22
開発    :VB.NET
データベース:SQL Server

VB.NETで帳票を出力するアプリケーションを開発しています。
帳票作成のボタンを押下してから結果が出るまでの間に、画面上を何度もクリックをすると誤作動が起こってしまいます。原因が分からず困っているのですが、詳しい方は是非教えていただけませんか?

事象について、詳しくは以下の通りです。
1.画面上で印刷ボタンを押し、データベースからデータを抽出して帳票を作成するプログラムです。
2.ボタンを押してから結果の出力まで数十秒かかる時があり、その間にForm上を連打し続けると、タイトルバーに「(応答なし)」の文字が出ます。
3.そのまま少し待つと、エラーメッセージ「オブジェクト参照がオブジェクト インスタンスに設定されていません。」が表示され、帳票は出力されません。
4.Form上のコントロールは、ボタン押下とほぼ同時に無効化しています。

以上です。
返信していただけるよう、よろしくお願いします。
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2004-11-17 19:11
しみこさん、こんばんは。

再入防止フラグを用意するとか。

コード:
Private Hoge As Boolean = False

Private Sub Button1_Click(ByVal s As Object, ByVal e As EventArgs) Handles Button1.Click
    If Hoge Then
        Exit Sub
    End If
    
    Hoge = True
    
    '処理
    
    Hoge = False
End Sub

mm
会議室デビュー日: 2004/09/25
投稿数: 17
投稿日時: 2004-11-17 19:32
しみこさん、こんばんは。

ボタン連打で、ボタン処理が再度走っているとしたら・・って仮定で。
再入してるのがボタン処理が終わってからだったとしたら、
メッセージの空読みで対応出来ないでしょうか。

Private Sub Button1_Click(・・・・)
 Test(); ← 帳票出力処理で非常に重い

 Do While PeekMessage(tpMsg,
            hwnd,
            WM_MOUSEFIRST,
            WM_MOUSELAST,
            PM_REMOVE)
Loop

End Sub

#VB6.0の時にこんな事をやっておりました。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-11-18 11:02
引用:

マミさんの書き込み (2004-11-17 19:32) より:
メッセージの空読みで対応出来ないでしょうか。


とりあえず、ボタンなどはEnabled = Falseにしているようなので、
最後にEnabled = Trueとやる直前にApplication.DoEvents()を
実行してみたらどうでしょうか?
# つまるところ、マミさんのとおおよそ同じことをやっていることになります。
※応答なしを解決するのは、もちょっとだけややこしいです。条件にもよりますし。
しみこ
会議室デビュー日: 2004/11/17
投稿数: 3
投稿日時: 2004-11-18 17:42
きくちゃんさん、マミさん、なちゃさん、ありがとうございました!
エラーを解決することが出来ました。
最終的に、なちゃさんに教えていただいたDoEvents()を帳票作成のループ中で実行し、解決しました。

---------------------------------------------------------------------------

ところで、エラーについて調べていて少し疑問を持ったので、よかったら教えていただけませんか?
疑問は、ボタンの無効化に関することです。

自分なりにエラーを分析し、2種類のエラーが存在すると考えました。

エラー@:タイトルバーに(応答なし)と表示される。
原因  :時間がかかる処理の実行中に、処理待ちのWindowsメッセージが溜まってしまうことによる。
対策  :DoEvents()によってたまったWindowsメッセージを明示的に処理する。

エラーA:エラーメッセージ「オブジェクト参照に…」が表示される。
     (インスタンスが null 参照になっている例外。)
原因  :帳票作成処理の再入による。
     (処理中にインスタンスの破棄を行っているからと考えます。)
対策  :ボタンの無効化(Enabled = False)、再入防止処理

疑問 → それぞれのエラーはそれぞれの対策によって解決されると考えられるのに、
     DoEvents()を行わないと、ボタンの無効化を行っても、再入防止処理を行っ
     ても、エラーAが発生してしまいました。
     (エラー@ももちろん発生しました。)
     上記の解釈自体が間違っているのでしょうか?
     
長々しい質問で申し訳ありません。
もしお分かりになる方がいたら、教えてください。よろしくお願いします。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-11-18 21:00
引用:

しみこさんの書き込み (2004-11-18 17:42) より:

エラー@:タイトルバーに(応答なし)と表示される。
原因  :時間がかかる処理の実行中に、処理待ちのWindowsメッセージが溜まってしまうことによる。

疑問 → それぞれのエラーはそれぞれの対策によって解決されると考えられるのに、
     DoEvents()を行わないと、ボタンの無効化を行っても、再入防止処理を行っ
     ても、エラーAが発生してしまいました。


ご自身で書いてらっしゃるように、Windowsメッセージはどんどんキューにたまっていきます。で、処理可能になった時点で一気に処理されていくわけですが…

ここで、Enabledとの絡みが出てきます。
Enabled = Falseの状態とは、簡単に言えば、キューから取り出したメッセージを破棄する様にしているということです。
で、この破棄という動作をするためには、メッセージをキューから取り出せないといけないわけで、つまり、メッセージを処理できずにキューにたまっていくだけの状態では、メッセージを破棄することもできていないということです。

で、最後にEnabled = Trueとしてイベントハンドラを抜けると、一気にたまったメッセージが処理されます。メッセージ処理が可能になった時点では、既にEnabled = Trueですから、結局Enabled=Falseによる防止はできていないということです。

Enabled = Trueの前にDoEventsを実行すると、そこで一旦メッセージの処理が行われますから、Enabled = Falseによる動作、つまりメッセージの破棄が行えるということです。
しみこ
会議室デビュー日: 2004/11/17
投稿数: 3
投稿日時: 2004-11-19 19:54
なちゃさん、わかりやすいご説明ありがとうございます。
Enabled=Falseの設定が他の処理と影響しあっているとは思いませんでした。
とても勉強になりました。
1

スキルアップ/キャリアアップ(JOB@IT)