3 回答
TA贡献1891条经验 获得超3个赞
一个区别是System.Threading.Timer在线程池线程上调度回调,而不是每次都创建一个新线程。如果你需要在应用程序的生命周期中多次发生这种情况,这将节省创建和销毁一堆线程的开销(这是一个非常耗费资源的过程,正如你引用的文章指出的那样),因为它会只是重用池中的线程,如果你一次有多个计时器,这意味着你将同时运行更少的线程(同时节省大量资源)。
换句话说,Timer效率会更高。它也可能更准确,因为Thread.Sleep只要你指定的时间(操作系统可能让它长时间睡眠),只保证等待至少。当然,Timer仍然不会完全准确,但目的是尽可能接近指定时间触发回调,而这不一定是意图Thread.Sleep。
至于销毁Timer,回调可以接受一个参数,所以你可以将Timer自己作为参数传递并在回调中调用Dispose(虽然我没有尝试过这个 - 我想有可能是Timer可能是在回调期间锁定)。
编辑:不,我想你不能这样做,因为你必须在Timer构造函数本身中指定回调参数。
也许是这样的?(再次,还没有真正尝试过)
class TimerState
{
public Timer Timer;
}
...并启动计时器:
TimerState state = new TimerState();
lock (state)
{
state.Timer = new Timer((callbackState) => {
action();
lock (callbackState) { callbackState.Timer.Dispose(); }
}, state, millisecond, -1);
}
锁定应防止计时器回调Timer在设置字段之前尝试释放计时器。
附录:正如评论者指出的那样,如果action()对UI有所作为,那么使用a System.Windows.Forms.Timer可能是更好的选择,因为它将在UI线程上运行回调。然而,如果不是这种情况下,它的到Thread.Sleep主场迎战Threading.Timer,Threading.Timer是要走的路。
TA贡献1801条经验 获得超16个赞
使用ThreadPool.RegisterWaitForSingleObject而不是计时器:
//Wait 5 seconds then print out to console.
//You can replace AutoResetEvent with a Semaphore or EventWaitHandle if you want to execute the command on those events and/or the timeout
System.Threading.ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(false), (state, bTimeout) => Console.WriteLine(state), "This is my state variable", TimeSpan.FromSeconds(5), true);
TA贡献2039条经验 获得超7个赞
我认为如果你真的想暂停应用程序指定的时间,Thread.Sleep就可以了。我认为人们说这是一个糟糕的设计的原因是因为在大多数情况下,人们实际上并不希望应用程序暂停。
例如,我正在使用pop3客户端,程序员使用Thread.Sleep(1000)等待套接字检索邮件。在这种情况下,最好将一个事件处理程序连接到套接字并在套接字完成后继续执行程序。
- 3 回答
- 0 关注
- 1296 浏览
添加回答
举报