为了账号安全,请及时绑定邮箱和手机立即绑定

使用Thread.Sleep和Timer进行比较以延迟执行

使用Thread.Sleep和Timer进行比较以延迟执行

C#
狐的传说 2019-09-02 09:05:58
我有一个方法应该延迟运行指定的时间。我应该用吗?Thread thread = new Thread(() => {    Thread.Sleep(millisecond);    action();});thread.IsBackground = true;thread.Start();要么Timer timer = new Timer(o => action(), null, millisecond, -1);我读过一些关于使用的文章Thread.Sleep是糟糕的设计。但我真的不明白为什么。但是对于使用Timer,Timer有配置方法。由于执行延迟,我不知道如何配置Timer。你有什么建议吗?或者如果你有延迟执行的替代代码也很感激。
查看完整描述

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是要走的路。


查看完整回答
反对 回复 2019-09-02
?
侃侃尔雅

TA贡献1801条经验 获得超15个赞

使用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);



查看完整回答
反对 回复 2019-09-02
?
largeQ

TA贡献2039条经验 获得超7个赞

我认为如果你真的想暂停应用程序指定的时间,Thread.Sleep就可以了。我认为人们说这是一个糟糕的设计的原因是因为在大多数情况下,人们实际上并不希望应用程序暂停。

例如,我正在使用pop3客户端,程序员使用Thread.Sleep(1000)等待套接字检索邮件。在这种情况下,最好将一个事件处理程序连接到套接字并在套接字完成后继续执行程序。


查看完整回答
反对 回复 2019-09-02
  • 3 回答
  • 0 关注
  • 1246 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信