我怎样才能停止System.Threading.Timer
它的回调方法。我参考MSDN
了,但找不到任何有用的东西。请帮忙。
问问题
30776 次
6 回答
15
首先,回调方法必须在范围内包含计时器实例。
然后是简单的咒语
timerInstance.Change( Timeout.Infinite , Timeout.Infinite ) ;
将关闭计时器。我相信,计时器可能会在更改后再次调用回调方法,具体取决于它所处的状态。
于 2012-08-13T16:41:29.537 回答
4
timer.Change(Timeout.Infinite, Timeout.Infinite);
于 2012-08-13T16:36:10.313 回答
2
尝试这个:
如果您愿意,可以让计时器继续触发回调方法并包含以下代码
private void CreatorLoop(object state)
{
if (Monitor.TryEnter(lockObject)
{
try
{
// Work here
}
finally
{
Monitor.Exit(lockObject);
}
}
}
也请查看此链接:
于 2012-08-13T16:38:52.977 回答
1
我发现 Change(Timeout.Infinite, Timeout.Infinite) 不太可靠,并在 AutoReset = false 的情况下切换到 System.Timers.Timer。
于 2013-05-23T12:36:53.307 回答
1
您可以简单地调用myTimer.Change(Timeout.Infinite, Timeout.Infinite)
.
dueTime
从技术上讲,只需要指定第一个参数 ( ) 即可Timeout.Infinite
让计时器停止。
有关详细信息,请参阅Timer.Change 方法。
于 2012-08-13T16:36:55.807 回答
1
Timer 的问题在于它可能在释放其所有者类之后被调用。以下实现通过使用 Timer 初始化程序的状态对象为我工作。堆在消耗之前不会删除该对象。这是我优雅地清理计时器回调的唯一方法。
using System;
using System.Threading;
namespace TimerDispose
{
/// <summary>
/// A timer-containing class that can be disposed safely by allowing the timer
/// callback that it must exit/cancel its processes
/// </summary>
class TimerOwner : IDisposable
{
const int dueTime = 5 * 100; //halve a second
const int timerPeriod = 1 * 1000; //Repeat timer every one second (make it Timeout.Inifinite if no repeating required)
private TimerCanceller timerCanceller = new TimerCanceller();
private Timer timer;
public TimerOwner()
{
timerInit(dueTime);
}
byte[] dummy = new byte[100000];
/// <summary>
///
/// </summary>
/// <param name="dueTime">Pass dueTime for the first time, then TimerPeriod will be passed automatically</param>
private void timerInit(int dueTime)
{
timer = new Timer(timerCallback,
timerCanceller, //this is the trick, it will be kept in the heap until it is consumed by the callback
dueTime,
Timeout.Infinite
);
}
private void timerCallback(object state)
{
try
{
//First exit if the timer was stoped before calling callback. This info is saved in state
var canceller = (TimerCanceller)state;
if (canceller.Cancelled)
{
return; //
}
//Your logic goes here. Please take care ! the callback might have already been called before stoping the timer
//and we might be already here after intending of stoping the timer. In most cases it is fine but try not to consume
//an object of this class because it might be already disposed. If you have to do that, hopefully it will be catched by
//the ObjectDisposedException below
dummy[1] = 50; //just messing up with the object after it might be disposed/nulled
//Yes, we need to check again. Read above note
if (canceller.Cancelled)
{
//Dispose any resource that might have been initialized above
return; //
}
if (timerPeriod != Timeout.Infinite)
{
timerInit(timerPeriod);
}
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("A disposed object accessed");
}
catch (NullReferenceException ex)
{
Console.WriteLine("A nulled object accessed");
}
catch (Exception ex)
{
}
}
public void releaseTimer()
{
timerCanceller.Cancelled = true;
timer.Change(Timeout.Infinite, Timeout.Infinite);
timer.Dispose();
}
public void Dispose()
{
releaseTimer();
dummy = null; //for testing
GC.SuppressFinalize(this);
}
}
class TimerCanceller
{
public bool Cancelled = false;
}
/// <summary>
/// Testing the implementation
/// </summary>
class Program
{
static void Main(string[] args)
{
var list = new System.Collections.Generic.List<TimerOwner>();
Console.WriteLine("Started initializing");
for (int i = 0; i < 500000; i++)
{
list.Add(new TimerOwner());
}
Console.WriteLine("Started releasing");
foreach (var item in list)
{
item.Dispose();
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
}
于 2017-06-16T19:28:52.310 回答