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自然会出错了。
请问这该如何解决呢?谢谢大家了!
8 个解决方案
#1
你在使用timer的时候,进行释放的时候,可以通过TimerExampleState来做处理。参看msdn中的例子。
如果不想再运行Timer了,最好在callback中,不要再用change来进行修改。
如果不想再运行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,还有其它一些例子也是这么用的,难道这样用不妥吗?请指点,如果不好的话,那这个该如何弄呢?谢谢!
另外,关于你说的“如果不想再运行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还在运行的情况,这就出现了异常。
他是在Timer的callback方法中自己判断并结束Timer,这个与我的不一样的。我是要外面控制Timer的结束。正因为我是在外面控制(调用Dispose方法),所以才会出现设置Timer为NULL的时候,而callback还在运行的情况,这就出现了异常。
#4
没错,
首先你需要用类的成员保存TimerExampleState,然后在CallBack函数中判断state,或者可以用一个成员来标示要进行dispose操作,
那么在类的Dispose中,先告诉当前状态,然后判断TimerExampleState对象是否已经关闭,然后带调用Timer的dispose。
首先你需要用类的成员保存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");
}
}
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
谢谢,太谢谢了!
#7
另外,我还想问问,我看到一种这样的用法:
public void Dispose()
{
if (_timer != null)
{
lock(this)
{
blnDisposed = true;
while(_timer != null)
Thread.Sleep(5);
}
}
我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
public void Dispose()
{
if (_timer != null)
{
lock(this)
{
blnDisposed = true;
while(_timer != null)
Thread.Sleep(5);
}
}
我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
#8
to 我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
其实类的dispose这个部分,不会在多线程中去掉用,因此我的想法和你一样,是没有必要的。
其实类的dispose这个部分,不会在多线程中去掉用,因此我的想法和你一样,是没有必要的。
#1
你在使用timer的时候,进行释放的时候,可以通过TimerExampleState来做处理。参看msdn中的例子。
如果不想再运行Timer了,最好在callback中,不要再用change来进行修改。
如果不想再运行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,还有其它一些例子也是这么用的,难道这样用不妥吗?请指点,如果不好的话,那这个该如何弄呢?谢谢!
另外,关于你说的“如果不想再运行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还在运行的情况,这就出现了异常。
他是在Timer的callback方法中自己判断并结束Timer,这个与我的不一样的。我是要外面控制Timer的结束。正因为我是在外面控制(调用Dispose方法),所以才会出现设置Timer为NULL的时候,而callback还在运行的情况,这就出现了异常。
#4
没错,
首先你需要用类的成员保存TimerExampleState,然后在CallBack函数中判断state,或者可以用一个成员来标示要进行dispose操作,
那么在类的Dispose中,先告诉当前状态,然后判断TimerExampleState对象是否已经关闭,然后带调用Timer的dispose。
首先你需要用类的成员保存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");
}
}
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
谢谢,太谢谢了!
#7
另外,我还想问问,我看到一种这样的用法:
public void Dispose()
{
if (_timer != null)
{
lock(this)
{
blnDisposed = true;
while(_timer != null)
Thread.Sleep(5);
}
}
我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
public void Dispose()
{
if (_timer != null)
{
lock(this)
{
blnDisposed = true;
while(_timer != null)
Thread.Sleep(5);
}
}
我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
#8
to 我觉得这里加lock没有任何必要吧?你觉得呢?谢谢!
其实类的dispose这个部分,不会在多线程中去掉用,因此我的想法和你一样,是没有必要的。
其实类的dispose这个部分,不会在多线程中去掉用,因此我的想法和你一样,是没有必要的。