源代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass t = new TestClass();
            t.Start();
            Thread.Sleep(30000);
            t.Dispose();
            Thread.Sleep(30000);
        }
    }    public class TestClass : IDisposable
    {
        private Timer _timer;        public void Start()
        {
            _timer = new Timer(new TimerCallback(JobCallBack), null, 1000, 1000);
        }        private void JobCallBack(object state)
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);
            Console.WriteLine("Starting...");
            Thread.Sleep(10000);
            Console.WriteLine("Complete");
            _timer.Change(1000, 1000);
        }        public void Dispose()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }
            Console.WriteLine("Disposed");
        }
    }
}
以上代码输出结果为:
Starting...
Complete
Starting...
Complete
Starting...
Disposed
Complete未处理的异常:  System.NullReferenceException: 未将对象引用设置到对象的实例。
   在 ConsoleApplication1.TestClass.JobCallBack(Object state) 位置 C:\ConsoleA
pplication1\Program.cs:行号 35
   在 System.Threading._TimerCallback.TimerCallback_Context(Object state)
   在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C
ontextCallback callback, Object state)
   在 System.Threading._TimerCallback.PerformTimerCallback(Object state)------------------------------------------
开始程序是正常运行的,但调用Dispose后程序发生异常,经过我分析,发现问题如下:
主程序方法 Main 中调用了Dispose,因此,TestClass 中的 _timer 为null了,而此时TestClass中的JobCallBack方法尚未结束,因此调用_timer.Change自然会出错了。请问这该如何解决呢?谢谢大家了!

解决方案 »

  1.   

    你在使用timer的时候,进行释放的时候,可以通过TimerExampleState来做处理。参看msdn中的例子。如果不想再运行Timer了,最好在callback中,不要再用change来进行修改。
      

  2.   

    谢谢,我先去看看例子。
    另外,关于你说的“如果不想再运行Timer了,最好在callback中,不要再用change来进行修改。”
    就拿我的那个callback函数来说吧,代码如下:
    private void JobCallBack(object state)
    {
    _timer.Change(Timeout.Infinite, Timeout.Infinite);
    Console.WriteLine("Starting...");
    Thread.Sleep(10000);
    Console.WriteLine("Complete");
    _timer.Change(1000, 1000);
    }
    我的这个callback函数中,用change来修改只是想临时禁止Timer,目的是防止这次调用还没完成,下次调用又来了,但是在我的callback完成后我还是需要继续Timer的。
    这个我看CS和Forum2,还有其它一些例子也是这么用的,难道这样用不妥吗?请指点,如果不好的话,那这个该如何弄呢?谢谢!
      

  3.   

    Knight94(愚翁) 你好,我刚刚看了下你说的TimerExampleState例子,那个例子好像是这样的:
    他是在Timer的callback方法中自己判断并结束Timer,这个与我的不一样的。我是要外面控制Timer的结束。正因为我是在外面控制(调用Dispose方法),所以才会出现设置Timer为NULL的时候,而callback还在运行的情况,这就出现了异常。
      

  4.   

    没错,
    首先你需要用类的成员保存TimerExampleState,然后在CallBack函数中判断state,或者可以用一个成员来标示要进行dispose操作,
    那么在类的Dispose中,先告诉当前状态,然后判断TimerExampleState对象是否已经关闭,然后带调用Timer的dispose。
      

  5.   

    sample code as follows:
    public class TestClass : IDisposable
    {
    private Timer _timer;
    private bool blnDisposed = false; public void Start()
    {
    _timer = new Timer(new TimerCallback(JobCallBack), null, 1000, 1000);
    } private void JobCallBack(object state)
    {
    _timer.Change(Timeout.Infinite, Timeout.Infinite);
    Debug.WriteLine("Starting...");
    Thread.Sleep(10000);
    Debug.WriteLine("Complete");
    if( !blnDisposed )
    _timer.Change(1000, 1000);
    else
    _timer = null;
    } public void Dispose()
    {
    if (_timer != null)
    {
    blnDisposed = true;
    while(_timer != null)
    Thread.Sleep(5);
    }
    Debug.WriteLine("Disposed");
    }
    }
      

  6.   

    另外,我还想问问,我看到一种这样的用法:
    public void Dispose()
    {
        if (_timer != null)
        {
            lock(this)
            {
                blnDisposed = true;
                while(_timer != null)
                    Thread.Sleep(5);
            }
    }
    我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
      

  7.   

    to 我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!其实类的dispose这个部分,不会在多线程中去掉用,因此我的想法和你一样,是没有必要的。