如何使用计时器替换线程.Azure工作者角色中的睡眠(..)



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

我很难理解的是如何对其进行编码。

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

_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();作为解决方案。这不是我在这里想要实现的。请注意帖子标题!

我认为,如果你想以这里概述的方式解决这种情况,你需要一个WaitHandle和一个Timer。

下面是简短的答案。长长的答案变成了一篇博客文章:HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread。睡眠

我使用了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;
        }
    }
}

最新更新