■80718 / inTopicNo.11) |
Re[7]: プログレスバーの処理遅延 |
□投稿者/ 魔界の仮面弁士 (799回)-(2016/08/05(Fri) 12:29:04)
|
■No80715 (真田昌幸 さん) に返信 > やるなら、ユーザーにシングルコアのPCがゼロであることを確認してからにはなります。 タスクマネージャーで、CPU が 100% に張り付いていないのであれば、 CPU は 1 コアで十分だと思います。
■No80689 (真田昌幸 さん) に返信 > プロパティ設定の(画面側での)タイミングの変更とか、 > あるいは環境面の改善で何とかなるかとかですね。 > 「手軽な」の意味は。
「DB 更新」が時間のかかる処理で、それが UI スレッドから呼ばれているのであれば、 Await を用いる(要 .NET 4.5 以降)を使うのが良い気がしますが、 そこまでするほどの課題では無いという判断なら、 進捗表示を行わないというのも、一つの道だとは思います。
> 現象としては、ProgressBarの目盛が全く進まない状態で本処理が終了し完了メッセージが出てしまうイメージ。 多分 ↓コレと同じですよね。 https://social.msdn.microsoft.com/Forums/ja-JP/0ff2009e-3d83-4099-9839-c043ac2a3d9e/100?forum=csharpgeneralja
であれば、No80701 でなちゃさんが書かれているように、 Value を「少し多く設定して戻す」方法で回避できませんでしたか?
'バーが進まないパターン Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown ProgressBar1.Style = ProgressBarStyle.Continuous ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 10000 ProgressBar1.Value = 0
For i = 1 To 10000 ProgressBar1.Value = i ProgressBar1.Update() Next
'本来は、UI スレッドで Sleep するべきでは無いけれど: System.Threading.Thread.Sleep(3000)
Me.Close() End Sub
'バーが進むが、80% 近辺で止まってしまい、100%にならない(MSDN Forum の質問例) Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown ProgressBar1.Style = ProgressBarStyle.Continuous ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 10000 ProgressBar1.Value = 0
'Invalidate + Update を Refresh に置き換えても良い For i = 1 To 10000 ProgressBar1.Invalidate() ProgressBar1.Value = i ProgressBar1.Update() 'Application.DoEvents() 'これを入れても効果は無い Next
System.Threading.Thread.Sleep(3000)
Me.Close() End Sub
'期待通り、100% になってから 3 秒後に閉じるが、要.NET 4.5 以降 'それ以前のバージョンでは、MSDN Forum の回答例のようにイベント待機に置き換える Private Async Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown ProgressBar1.Style = ProgressBarStyle.Continuous ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 10000 ProgressBar1.Value = 0
For i = 1 To 10000 ProgressBar1.Value = i ProgressBar1.Refresh() Next
Await Task.Delay(3000)
Me.Close() End Sub
' No80701 のなちゃさん案 'わざと行き過ぎてから戻す方法であれば、重い処理でもバーが更新される Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown ProgressBar1.Style = ProgressBarStyle.Continuous ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 10000 ProgressBar1.Value = 0
' http://dobon.net/vb/dotnet/control/pbdisableanimation.html ProgressBar1.Maximum += 1 For i = 1 To 10000 ProgressBar1.Value = i + 1 ProgressBar1.Value = i Next ProgressBar1.Maximum -= 1
System.Threading.Thread.Sleep(3000)
Me.Close() End Sub
もしもなちゃさん案で回避できるのであれば、ProgressBar 継承クラスで、 Value プロパティをシャドウイングしてみては如何でしょうか。
Public Overloads Property Value() As Integer Get Return MyBase.Value End Get Set(ByVal value As Integer) If value = Me.Maximum Then Me.Maximum += 1 MyBase.Value = value + 1 MyBase.Value = value Me.Maximum -= 1 Else MyBase.Value = value + 1 MyBase.Value = value End If End Set End Property
こうしておけば、 For i = 1 To 10000 ProgressBar1.Value = i Next System.Threading.Thread.Sleep(3000) であったとしても、100% まで到達するようです。
ただし、元の Value は Overridable では無いため、 この実装は Overloads または Shadows になります。そのため、 DirectCast(ProgressBar1, ProgressBar).Value = i のように呼ばれた場合は、アニメーション効果をキャンセルできません。
|
|