4

スタック トレースは次のとおりです。

2012-03-16 19:15:09Z E System.NullReferenceException: オブジェクト参照がオブジェクトのインスタンスに設定されていません。
System.Timers.Timer.set_Enabled(ブール値)
で System.Timers.Timer.Stop()

コードは次のとおりです。

プライベート メンバー変数として宣言されたタイマー。

Private _myTimer As System.Timers.Timer

タイマーメソッドを初期化します。

Private Sub InitializeMyTimer()

    _myTimer = New System.Timers.Timer

    _myTimer.Interval = My.Settings.TimeoutSeconds * 1000
    _myTimer.Start()

    AddHandler _myTimer.Elapsed, AddressOf MyTimer_Elapsed

End Sub

タイマー経過メソッド。WsMethodAsync は、.asmx Web サービス メソッドを呼び出します。

Private Sub MyTimer_Elapsed(ByVal sender As Object, ByVal e As     System.Timers.ElapsedEventArgs)

    Try

        _myTimer.Stop()

        Using thisWSHelper As New WSHelper

            thisWsHelp.WsMethodAsync()

        End Using

        _myTimer.Start()

    Catch ex As Exception

      LogAndShowException(ex)

    End Try

End Sub

タイマーには値が必要です。そうしないと、Timer.Stop() 呼び出しで例外がスローされます。これは散発的なエラーであり、誰かが以前にこれを経験したことがあるかどうか、または何が原因であるかについて何か考えがあるかどうかを確認しようとしています. タイマーの Elapsed イベントのイベント ハンドラーで WinForms アプリケーションで発生していますが、ユーザーのコンピューターでは散発的にしか発生していません。自分でエラーを再現できませんでした。

4

2 に答える 2

2

System.Timers.TimerクラスがIDisposableを実装し、タイマーを適切に処理するためのコードを記述したことに気付いたとしましょう。

Private Sub OnDisposed(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Disposed
    If myTimer IsNot Nothing Then
        myTimer.Dispose()
        myTimer = Nothing
    End If
End Sub

はい、それはたまに大騒ぎになるでしょう。Elapsedイベントは、スレッドプールスレッドによって発生し、任意の奇数時に実行を開始できます。スレッドプールが特にビジー状態の場合は、数秒かかることがあります。タイマーを破棄しても、イベントの実行が妨げられることはありませ。tpスレッドはすでに実行中です。したがって、この特定のコードを使用すると、NREを取得する可能性が高くなります。たまに、コードをデバッグするときは決してありません。

System.Timers.Timerを制御された方法で停止することは非常に困難です。無効にした後、Elapsedイベントが発生しないことを確認することはできません。防御的に書いて、それが可能であることを心に留めておいてください。そして、System.Threading.Timerを支持します。

于 2012-04-04T17:32:38.187 に答える
1

まず、これらのランダムな例外が表示される理由:

ASystem.Timers.TimerSystem.Threading.Timerとして使用し、Hans Passant が言ったように、各反復は別のスレッドで行われます。これによりElapsed、タイマーを無効にした後にイベントを発生させることができます。これは、前の反復が完了する前に新しい反復を開始できるためです。

動作方法、System.Timers.Timerそれを無効にすると、基になるものが破棄System.Threading.Timerされ、Nothing に設定されます。まれな (この単語は冗長ですか?) 競合状態では、タイマーがDisposeNothing に設定されている間に、その基になるタイマーで実行しようとするため、NullReferenceException.


Timer.AutoReset1 つの解決策は、プロパティを Falseに設定し、Elapsedイベントでタイマーを再起動することです。

于 2012-04-04T21:45:15.410 に答える