1

最近、私はで働いていsystem.form.timerますUI thread。バックグラウンド スレッドでタイマーを停止することはできBeginInvokeますが、cross-threading exception. ただし、system.timers.timerタイマーによって作成されたバックグラウンド スレッドから停止および開始できるようです。どうしてこれなの?はsystem.form.timer停止できますが、バックグラウンド スレッドから有効にすることはできませんか? これは私には少し奇妙に思えます。

System.Form.Timer コード

動作しません

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim BW As BackgroundWorker = New BackgroundWorker
    AddHandler BW.DoWork, AddressOf CheckTimer
    BW.RunWorkerAsync()
End Sub

Private Sub CheckTimer()
    Timer1.Stop()
    Timer1.Start()
    MsgBox("Stopped and Started Timer")
End Sub

作品

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim BW As BackgroundWorker = New BackgroundWorker
    AddHandler BW.DoWork, AddressOf CheckTimer
    BW.RunWorkerAsync()
End Sub

Private Sub CheckTimer()
    Timer1.Stop()
    Me.BeginInvoke(New TimerStart(AddressOf TimerStartFunction))
    MsgBox("Stopped and Started Timer")
End Sub

Private Delegate Sub TimerStart()

Private Sub TimerStartFunction()
    Timer1.Start()
End Sub

System.Timers.Timer コード

作品

Dim aTimer As System.Timers.Timer

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    aTimer = New System.Timers.Timer(5000)
    AddHandler aTimer.Elapsed, AddressOf OnTimedEvent
    aTimer.Enabled = True
End Sub

Sub OnTimedEvent()
    aTimer.Stop()
    aTimer.Start()
    MsgBox("Stopped and Started Timer")
End Sub
4

1 に答える 1

5

Winforms の Timer クラスは多少スレッド セーフですが、ユーザーを満足させるには不十分です。その Start() メソッドを呼び出すと、WM_TIMER メッセージを Tick イベントに変換する隠しウィンドウが作成されます。

ワーカー スレッドでこれを行うと、問題が発生する傾向があります。これらの WM_TIMER メッセージは、スレッドがメッセージ ループを実行するときにのみディスパッチされます。通常、ワーカー スレッドはこれを行わず、Application.Run() を呼び出しません。そのため、タイマーはカチカチ音をたてません。

それ以外の場合、Stop() メソッドの呼び出しは問題ありません。コードが間違ったスレッドで実行されていても、非表示のウィンドウを見つける方法を知っています。BeginInvoke() で見つけた回避策は、UI スレッドで Start() を正しく呼び出し、正しい所有者スレッドで作成された隠しウィンドウを取得するため、機能します。System.Timers.Timer にはこの問題はありません。WM_TIMER に依存せず、代わりに System.Threading.Timer を使用します。これは、CLR によって管理される専用のワーカー スレッドによってサポートされます。このタイマーはかなり危険であることに注意してください。ワーカー スレッドで MsgBox() を呼び出すことは、根本的に間違っています。UIウィンドウの背後にあるため、ユーザーがそれを見ることはない可能性が高い.

あなたが実際に何をしようとしているのかわからないので、それ以外の方法でより良いアドバイスを提供することはできません。注意してください、あなたは火遊びをしています。

于 2013-08-31T11:49:00.737 に答える