DOBON.NET DOBON.NETプログラミング掲示板過去ログ

別ThreadからのUI操作について

環境/言語:[OS : Windows 7 / 言語 : Visual Basic .NET / .NET Framework : 4]
分類:[.NET]

【解決したい問題】

初めての投稿です。至らない点等あるかと思いますが、よろしくお願いいたします。
早速ですが、以下のコードについて質問させていただきます。

処理:ボタンを押したらDBを読み込む
目標:この処理に数分時間がかかるため、処理中、Threading.Timerを使用して一定時間ごとにプログレスバーを動かす

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim timerDelegate As New Threading.TimerCallback(AddressOf MyClock)
Dim timer As New Threading.Timer(timerDelegate, Nothing, 0, 1000)

Call selectDB() 'DBを読み込む処理

End Sub

Delegate Sub SetProgressBarDelegate()

Private Sub SetProgressBar()
Console.WriteLine("C")
ProgressBar1.Value += 10
End Sub

Public Sub MyClock(ByVal o As Object)
Console.WriteLine("A")
Me.Invoke(New SetProgressBarDelegate(AddressOf SetProgressBar))
Console.WriteLine("B")
End Sub

問題:SetProgressBar()が一度も実行されないため、プログレスバーは動きません。
詳細:デバッグにより、以下がわかっています。
Console.WriteLine("A")は一定時間ごとに実行されています。
Console.WriteLine("B")は1回も実行されません。
Console.WriteLine("C")は1回も実行されません。
よって、Me.InvokeにてMyClock()の処理が止まっている(Me.InvokeにてMyClock()を抜けている)と推測されます。
selectDB() の処理は順調に進みます。

コードより、目標の達成を妨げている要因が特定できれば、ご教授頂けますでしょうか?
よろしくお願いいたします。
■No31731に返信(えいさんの記事)
> 処理:ボタンを押したらDBを読み込む
> 目標:この処理に数分時間がかかるため、処理中、Threading.Timerを使用して一定時間ごとにプログレスバーを動かす

UI スレッドで重い処理を行わせているのであれば、
その間、プログレスバーを動かすことはできません。

DB 操作を非同期処理に変更して、データの読み込みが終わった後で、
その結果データを UI スレッドに渡す仕組みに置き換えましょう。


> Private Sub Button1_Click(…
> Call selectDB() 'DBを読み込む処理
> End Sub

この場合、Button1_Click は継続実行中ですよね。
UI スレッド側は、メッセージループを処理する余裕が無い状態なので、
Invoke で依頼を受けたとしても、それを画面に反映させることができません。


> よって、Me.InvokeにてMyClock()の処理が止まっている
> (Me.InvokeにてMyClock()を抜けている)と推測されます。

今回の場合、Invoke で依頼された処理が実行されるのは、
Button1_Click が End Sub に到達した後になってしまうでしょう。
■No31732に返信(魔界の仮面弁士さんの記事)
魔界の仮面弁士さん、初歩的な質問にもかかわらず、丁寧なご説明有難うございました。
教えていただいた通りに修正し、無事目的を達成することができました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板