.net 我可以在其回调中处理Threading.Timer吗?
我正在使用.net 我可以在其回调中处理Threading.Timer吗?,.net,callback,timer,dispose,.net,Callback,Timer,Dispose,我正在使用Threading.Timer,例如: new Timer(new TimerCallback(y=> { try { Save(Read(DateTime.Now)); // here i want to dispose this timer } catch { } }),null,100000,10000); 如何在回调中处理此计时器。还是变通
Threading.Timer
,例如:
new Timer(new TimerCallback(y=>
{
try
{
Save(Read(DateTime.Now));
// here i want to dispose this timer
}
catch
{
}
}),null,100000,10000);
如何在回调中处理此计时器。还是变通办法?
更新:让我解释一下情况。我想尝试调用“Save”方法,但它会引发异常。如果它能工作,我需要停止计时器。试试这个:
Timer timer = null;
timer = new Timer(new TimerCallback(y =>
{
try
{
Save(Read(DateTime.Now));
// here i want to dispose this timer
timer.Dispose();
}
catch
{
}
}));
timer.Change(10000, 10000);
编辑:
根据Chuu的建议,我稍微修改了上面的代码。请注意,如果不同的计时器事件同时调用TimerCallback,
timer.Dispose
可能会被多次调用。幸运的是,计时器
不关心它是否被多次处理。您需要将计时器的引用保存在一个变量中-
public class MyClass
{
private Timer _timer;
public void StartTimer()
{
_timer = new Timer(new TimerCallback(y=>{
try
{
Save(Read(DateTime.Now));
_timer.Dispose();
}
catch {
}
}),null,100000,10000);
}
}
注意:这是未经测试的代码。请检查它是否工作并更新。您必须将对计时器的引用存储在某个位置,并将其作为状态传递给计时器对象本身。尝试创建类似以下内容的类:
public class TimerContainer
{
public Timer Timer { get; set; }
}
然后在您的方法中使用它,如下所示:
Action<object> tcb = state =>
{
var container = (TimerConatiner)state;
try
{
Save(Read(DateTime.Now));
container.Timer.Dispose();
}
catch
{
// whatever...
}
};
var container = new TimerContainer();
container.Timer = new Timer(tcb, container, 100000, 10000);
Action tcb=state=>
{
var容器=(TimerConatiner)状态;
尝试
{
保存(读取(DateTime.Now));
container.Timer.Dispose();
}
抓住
{
//不管怎样。。。
}
};
var container=new TimerContainer();
container.Timer=新计时器(tcb,container,100000,10000);
这里有一个更好的方法。当您使用只有一个参数(TimerCallback)的构造函数时,传递给回调的状态将是计时器本身
Timer timer = new Timer(o =>
{
((Timer)o).Dispose();
//Your code here
});
//Start the timer
timer.Change(100000,10000);
以下是msdn文档中的一个示例:
public void StartTimer(int dueTime)
{
Timer t = new Timer(new TimerCallback(TimerProc));
t.Change(dueTime, 0);
}
private void TimerProc(object state)
{
// The state object is the Timer object.
Timer t = (Timer) state;
t.Dispose();
Console.WriteLine("The timer callback executes.");
}
如果使用多线程或多任务处理,请小心!如果是这样,下面是CancelAfter方法extensor(.net 4.0)的代码和解决方案:
private static object syncObj=new object();
public static void CancelAfter(此CancellationTokenSource源代码,int-timeout毫秒,操作代码=null)
{
if(timeoutmillizes==0)返回;//无超时
if(source==null)
{
抛出新的NullReferenceException();
}
如果(超时毫秒<-1)
{
抛出新ArgumentOutOfRangeException(“超时”);
}
计时器=新计时器(委托(对象自身)
{
锁(同步对象)
{
尝试
{
如果(空!=代码)
code.Invoke();
source.Cancel();
((IDisposable)self.Dispose();
}
捕获(ObjectDisposedException)
{
}
}
});
timer.Change(timeout毫秒,-1);
}
}
问候,,
Juanlu,ElGuerre你有没有试过把它分配给一个变量,然后访问这个变量?为什么你不能简单地用
语句把计时器
包装在中呢?@Cody,因为计时器可能会比预期的更早被释放。哇,我想把这个问题弄得复杂一些。显而易见的解决方案确实是一个Dispose
语句。我以为这已经被排除在“不可选项”之外了。我想这太明显了:-)我的损失,你的收获。我经常把事情弄得太复杂+我不认为这是100%线程安全的,理论上可能会发生以下一系列事件(不可思议地不太可能):1。计时器已创建。2.3.线程池4上的回调火。5.分配发生。线程安全的方法可能是创建具有无限超时的计时器,以在线程池回调之前强制赋值,然后使用Change()设置循环属性。@Chuu:这一点很好。我认为你是对的。我相应地改变了答案。
private static object syncObj = new object();
public static void CancelAfter(this CancellationTokenSource source, int timeoutMilliseconds, Action code = null)
{
if (timeoutMilliseconds == 0) return; // No timeout
if (source == null)
{
throw new NullReferenceException();
}
if (timeoutMilliseconds < -1)
{
throw new ArgumentOutOfRangeException("timeout");
}
Timer timer = new Timer(delegate(object self)
{
lock (syncObj)
{
try
{
if (null != code)
code.Invoke();
source.Cancel();
((IDisposable)self).Dispose();
}
catch (ObjectDisposedException)
{
}
}
});
timer.Change(timeoutMilliseconds, -1);
}
}