在广泛阅读了SO后,我了解到Thread.Sleep
是a bad idea。相反,普遍的共识是服务器端任务应该使用Timer
,threadpool
或者可以使用Join()
。我应该使用Timer,ThreadPool,AutoResetEvent还是使用模拟“加入”?
一个article提到处置定时器的困难。
另一个article提及使用waitOne
问题
什么是推出一个长期运行的任务,将重复每隔30秒,1分钟或5分钟时要使用正确的方法?约束条件是,如果该任务的上一次运行比间隔(32秒或7分钟)更长,那么我希望该选项杀死前一个实例或不执行新实例。
一个潜在的疑难杂症的是,我打算使用为使用模拟上这些线程要么WindowsImpersionationContext,P /调用LogonUserEX,或DCOMShim根据需要。
我不知道采取什么方法,为什么。
可能的答案1
这个例子似乎简单明了,用最少的代码混乱
// initially set to a "non-signaled" state, ie will block
// if inspected
private readonly AutoResetEvent _isStopping = new AutoResetEvent(false);
/// <summary>
/// from...
/// https://stackoverflow.com/questions/2822441/system-timers-timer-threading-timer-vs-thread-with-whileloop-thread-sleep-for-p/2822506#2822506
/// </summary>
public void SampleDelay1()
{
TimeSpan waitInterval = TimeSpan.FromMilliseconds(1000);
// will block for 'waitInterval', unless another thread,
// say a thread requesting termination, wakes you up. if
// no one signals you, WaitOne returns false, otherwise
// if someone signals WaitOne returns true
for (; !_isStopping.WaitOne(waitInterval);)
{
// do your thang!
}
}
可能的答案2
这个例子提供了类似的功能,但使用匿名类型这在那些不符合其编码标准的公司中可能是不允许的。
/// <summary>
/// Disposable Timer instance from
/// https://stackoverflow.com/questions/391621/compare-using-thread-sleep-and-timer-for-delayed-execution
/// </summary>
class TimerStackOverFlow
{
// Created by Roy Feintuch 2009
// Basically we wrap a timer object in order to send itself as a context in order
// to dispose it after the cb invocation finished. This solves the problem of timer
// being GCed because going out of context
public static void DoOneTime(ThreadStart cb, TimeSpan dueTime)
{
var td = new TimerDisposer();
// Is the next object System.Timers, or System.Threading
var timer = new Timer(myTdToKill =>
{
try
{
cb();
}
catch (Exception ex)
{
Trace.WriteLine(string.Format("[DoOneTime] Error occured while invoking delegate. {0}", ex), "[OneTimer]");
}
finally
{
((TimerDisposer)myTdToKill).InternalTimer.Dispose();
}
},
td, dueTime, TimeSpan.FromMilliseconds(-1));
td.InternalTimer = timer;
}
}
class TimerDisposer
{
public Timer InternalTimer { get; set; }
}
谢谢,我刚刚更新了一个潜在的问题...冒充的问题。 – LamonteCristo 2011-01-19 17:53:28