【问题标题】:How to use a Timer to replace Thread.Sleep(...) in an Azure Worker Role?如何使用计时器替换 Azure Worker Role 中的 Thread.Sleep(...)?
【发布时间】:2013-02-05 12:34:44
【问题描述】:

有很多人说在Azure Worker Role 中使用Timer 而不是Thread.Sleep(...)。没有问题。

我很难理解的是如何编写代码。

目前,我有以下(伪代码)

_timer.Elapsed += (sender, args) => DoWork();

public override void Run()
{
    while(true)
    {
        DoWork();
    }
}

public void DoWork()
{
    try
    {
        _timer.Stop();

        // Now - do stuff ....

     }
     catch(....) { ... }

     _timer.Start()
}

然后发生的情况是,代码进入DoWork() 方法一次,DoesStuff(tm).. 很好.. 启动计时器(比如 .. 间隔 30 秒),然后退出该方法。

然后,它返回到该循环中的主 Run() 方法。因此它立即返回并再次进入DoWork() 方法.. 而不是等待计时器将其关闭。

所以我不确定如何用计时器替换任何Thread.Sleep(...)

有什么线索吗?

澄清

我不想退出Run() 方法:) 我很高兴能一直循环下去。我坚持的是,替换标准的Thread.Sleep(...) 调用(阻塞线程)并用大多数人建议的Timer 替换它。

更新

请不要链接或建议我使用cancelSource.Token.WaitHandle.WaitOne(); 作为解决方案。这不是我想要在这里实现的。请注意帖子标题!

【问题讨论】:

  • 如何将 DoWork() 置于无限循环之外,并将旧的 Thread.Sleep(10000) 放入该循环中。这个想法是只初始化一次计时器,您可以在 Run() 方法中执行它。
  • 您是否阅读了关于替换 Thread.Sleep(..) 的开头行,因为它是 NotGood(tm)?
  • 如果我理解正确,这个想法是 WorkerRole 永远不会出现在 Run() 方法中,否则你的工作角色将重新启动 (stackoverflow.com/questions/9561746/…)。我想我不明白为什么这是一个坏主意?您是否正在寻找要安排“DoStuff()”每 30 秒调用一次的功能?
  • 啊对不起。好的,我不想退出 Run() 方法(所以你是对的)。但我不想使用Thread.Sleep(..) 来“暂停”工作人员(一段时间)。相反,我想使用计时器。
  • 关于这个问题的第一个搜索结果给出了另一个 SO 问题,答案足够优雅,您只需在“do stuff”部分启动计时器,标记为重复问题。 stackoverflow.com/questions/9561746

标签: c# .net azure timer azure-worker-roles


【解决方案1】:

我认为,如果您想按照您在此处概述的方式解决这种情况,您将需要一个 WaitHandle 和一个计时器。

简短的答案在下面。长答案变成了一篇博文:HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep

我将 EventWaitHandle 与 Timer 一起使用,并提出了以下解决方案:

public class WorkerRole : RoleEntryPoint
{
    Waiter waiter;

    public override bool OnStart()
    {
        waiter = new Waiter(WorkerConfiguration.WaitInterval);
        return base.OnStart();
    }

    public override void Run()
    {
        while (true)
        {
            DoWork();
            waiter.Wait();
        }
    }

    public void DoWork()
    {
        // [...]
    }
}

这里是服务员类:

public class Waiter
{
    private readonly Timer timer;
    private readonly EventWaitHandle waitHandle;

    public Waiter(TimeSpan? interval = null)
    {
        waitHandle = new AutoResetEvent(false);
        timer = new Timer();
        timer.Elapsed += (sender, args) => waitHandle.Set();
        SetInterval(interval);
    }

    public TimeSpan Interval
    {
        set { timer.Interval = value.TotalMilliseconds; }
    }

    public void Wait(TimeSpan? newInterval = null)
    {
        SetInterval(newInterval);
        timer.Start();
        waitHandle.WaitOne();
        timer.Close();
        waitHandle.Reset();
    }

    private void SetInterval(TimeSpan? newInterval)
    {
        if (newInterval.HasValue)
        {
            Interval = newInterval.Value;
        }
    }
}

【讨论】:

  • 哇哦!非常感谢你 - 我今晚回家时会试一试。 /我低头。
  • 注意:我也很喜欢你有一个高级解决方案(在你的博客上),它使用时间 intervals :) 也非常好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
相关资源
最近更新 更多