タイマー処理と他の処理をうまく制御するには?

解決


Oyakata  2007-03-02 21:49:57  No: 135604

(WinXP、VB.NET2003)
いつも初心者衆(私も)がお世話になっております。

先日Label上で文字列が流れる(マーキー風?)処理を作ってみました。
# 仕事の合間ができたので多少の勉強を兼ねて
# Private WithEvents m_timer As New Timer と宣言したタイマーの
# TickイベントでGraphicsオブジェクトを操作(DrawString)する程度の
# ものなんですが・・・

そこで質問ですが、
例えば上記の処理で"しばらくお待ち下さい"のような文字を流しつつ
その裏でなんらかの処理(集計ループとか)ができないかと考えたのですが

単純にButton1_Clickで
m_timer.Start()
Call 処理メソッド
'm_timer.Stop()
ですと、思惑通りの動作にはなりませんでした。
# Call処理が終わるまで文字が流れない?感じです。

このような場合なにをキーワードにどういった事を
ヘルプ等で調べれば良いのかも思いつかず
どんな感じで質問すればよいかも悩みまして
タイトルも含めて文章がヒドイとは思いますが
なにかこう手法とゆうか助言頂ければ幸いです。


我龍院  2007-03-03 22:15:00  No: 135605

「vb.net マルチスレッド  処理の進行状況」などでググル。


Oyakata  2007-03-05 21:58:03  No: 135606

返信ありがとうございます。

助言を参考に自分なりにWEB検索等で調査してみたところ
UpdateメソッドやApplication.DoEventsメソッドによる
コントロールの再描画では無理のようでした(たぶん)

そうなるとご指摘の通り別スレッドで処理ということに
なるんだとは思いましたが、例えばデリゲートとか今の
私にはまだ難しいキーワードも出てきてハードルが高そうです・・・

># 仕事の合間ができたので多少の勉強を兼ねて
では全然無理そうなので
きちんと時間が取れる時に勉強しようと思います。


魔界の仮面弁士  2007-03-05 22:51:28  No: 135607

> (WinXP、VB.NET2003)
う〜ん、残念。

VB2005 なら、別スレッドでの処理+デリゲートという複雑(?)な部分を、
単純なイベント処理による「BackgroundWorker クラス」として扱えるので、
比較的簡単に実装できるのですけれどね。

Private Sub Button1_Click(……
  BackgroundWorker1.RunWorkerAsync()  '時間のかかる処理を非同期で開始
End Sub

Private Sub BackgroundWorker1_DoWork(……
  '---------
  '時間のかかる処理をここに記述
  '---------
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(……
  MessageBox.Show("別スレッドの処理が完了しました。")
End Sub


魔界の仮面弁士  2007-03-05 22:54:47  No: 135608

# URL 貼り忘れた……。

VB2005 の BackgroundWorker クラスによる実装例と、
VB.NET 2003 の Thread クラスによる実装例です。

もっとも、すでにご覧になっているかも知れませんけれども。(^^;

http://www.microsoft.com/japan/msdn/vbasic/migration/tips/BackgroundWorker/


Oyakata  2007-03-06 01:35:38  No: 135609

魔界の仮面弁士さん、回答ありがとうございます。

># URL 貼り忘れた……。
を参考に、まったくの見よう見まねですが
以下のコードでそれっぽく動いてくれてるみたいです。

Private WithEvents m_timer As New Timer
Private m_left As Integer
'
Private Delegate Sub TimerProcessDelegate()
Private m_thread As System.Threading.Thread

' 実行Button
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    m_left = Me.Label1.Width
    m_timer.Interval = 5
    ' 別スレッド…?
    m_thread = New System.Threading.Thread(AddressOf doWork)
    m_thread.Start()
End Sub

' タイマー
Private Sub Timer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_timer.Tick
    ' マーキー?処理
    Dim g As Graphics = Me.Label1.CreateGraphics()
    Dim siz As SizeF = g.MeasureString(Me.Label1.Text, Me.Label1.Font)
    g.Clear(Me.Label1.BackColor)
    g.DrawString(Me.Label1.Text, Me.Label1.Font, New SolidBrush(Me.Label1.ForeColor), m_left, 4)
    m_left -= 1
    If m_left < CInt(siz.Width) * -1 Then
        m_left = Me.Label1.Width
    End If
    g.Dispose()
End Sub

' 別スレッド処理…?
Private Sub doWork()
    Me.Invoke(New TimerProcessDelegate(AddressOf TimerStart))
    '
    For i As Integer = 0 To 50000
        ' テストループ(実際は処理を記述)
        Me.Label2.Text = i.ToString
    Next
    '
    Me.Invoke(New TimerProcessDelegate(AddressOf TimerStop))
End Sub

Private Sub TimerStart()
    Me.Button1.Enabled = False
    m_timer.Start()
End Sub

Private Sub TimerStop()
    Me.Button1.Enabled = True
    m_timer.Stop()
End Sub

結局、Delegate・Invoke・AddressOfなど
ほとんど打ったことのないキーワードに
ついては相変わらず意味不明ですが^^;
# 徐々に理解できればと・・

とりあえず解決チェック付けますが、まだまだ勉強不足ですので
お気づきの点などあれば、ご指摘お願いします。


Oyakata  2007-03-06 01:38:17  No: 135610

>とりあえず解決チェック付けますが、
付けてないし・・すいませんでした。


我龍院  2007-03-06 04:18:22  No: 135611

>Me.Label2.Text = i.ToString
メインスレッドから操作していないのでこれはダメでしょう。

Private Delegate Sub SetTextDelegate(ByVal objText As Object, _
            ByVal strText As String)

Private Sub SetText(ByVal objText As Object, _
                         ByVal strText As String)
    DirectCast(objText, Label).Text = strText
End Sub

For i As Integer = 0 To 50000
    ' テストループ(実際は処理を記述)
    Try
         Me.Invoke(New SetTextDelegate(AddressOf SetLabelText), _
                   Me.Label2, i.ToString)
       Application.DoEvents()
    Catch
         MsgBox("操作が取り消されました")
         Return
    End Try
Next
こんなことするのかな。


Oyakata  2007-03-06 22:20:51  No: 135612

我龍院さん、再度返信ありがとうございます。

>メインスレッドから操作していないので
なるほど。かなりぼんやりとですが
今回自分がやろうとしてる事(マルチスレッド?)についての
意味や手法など徐々に理解していけそうな予感がしてきました。

>こんなことするのかな。
(現在の処理件数というか)こんな感じです^^
サンプルありがとうございます。とても参考になります。

タイマー部分は大丈夫そう(?)なので、テスト用ではなく
実際のソースにうまく組み込めるよう更に勉強致します。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加