2

今日あるマシンで発生した NullReference 例外の説明はありますか? 私のパソコンでは再現できません…。

class Test
{
  Timer timer_;
  public void Init()
  {
    timer_ = new Timer();
    timer_.Interval = 10000;
    timer_.Tick += OnTimerTick;
    timer_.Start();
  }

  private void OnTimerTick(object sender, EventArgs e)
  {
    timer_.Stop();
    timer_ = null; <--- Null Ref occurs
  }
}

Mark Hall と Rich Okelly の素晴らしいアドバイスに基づくソリューション

private void OnTimerTick(object sender, EventArgs e)
{
    var localTimer = Interlocked.Exchange(ref timer_, null);
    if (localTimer != null)
    {
        localTimer.Stop();
        localTimer.Tick -= OnTimerTick;
        localTimer.Dispose();

        // doing staff
    }
}
4

3 に答える 3

3

タイマーを null に設定する前に、OnTimerTick イベントを削除してみてください。これにより、null に設定している間は発生しなくなりますが、10 秒のワンショットを作成する可能性は低いため、null に設定する前にタイマーを破棄してみてください。

すなわち

private void OnTimerTick(object sender, EventArgs e) 
{ 
    timer_.Stop(); 
    timer_.Tick -= OnTimerTick;
    timer_.Dispose();
    timer_ = null; 
}
于 2012-07-04T15:31:37.033 に答える
2

null 参照例外は、実際には上記の行で発生すると思います: at timer_.Stop().

何が起こったのかというと、Tick イベントが発生し、別のスケジュールがスケジュールされ、最初の Tick イベントの結果としてタイマーが停止し、null に設定されました。2 番目の Tick イベントは、現在 null になっている Timer で Stop を呼び出そうとします。

これを回避するには、Interlocked メソッドを使用できます。

private void OnTimerTick(object sender, EventArgs e)
{
  var localTimer= Interlocked.Exchange(ref timer_, null);
  if (localTimer != null) 
  {
     localTimer.Stop();
  }
}
于 2012-07-04T15:29:17.473 に答える