简体   繁体   English

如何使用计时器替换Azure Worker角色中的Thread.Sleep(...)?

[英]How to use a Timer to replace Thread.Sleep(…) in an Azure Worker Role?

There's plenty of examples of people saying to use a Timer instead of Thread.Sleep(...) in an Azure Worker Role . 人们说在Azure Worker Role使用Timer而不是Thread.Sleep(...)的例子很多。 No probs with that. 没有问题。

What I'm struggling to understand is how to code this. 我正在努力理解的是如何对此进行编码。

Currently, I have the following (pseduo code) 目前,我有以下(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()
}

And what happens, is that the code enters the DoWork() method once and DoesStuff(tm) .. fine .. starts the timer (say .. with a 30 second interval) and then exits that method. 发生的是,代码一次进入DoWork()方法, DoesStuff(tm) .. fine ..启动计时器(例如,以30秒为间隔),然后退出该方法。

Then, it returns back to the main Run() method .. which is in that loop. 然后,它返回到该循环中的主Run()方法.. So it immediately comes back around and enters the DoWork() method again .. instead of waiting for the timer to fire it off. 因此它立即返回并再次进入DoWork()方法..而不是等待计时器将其触发。

So I'm not sure how to replace any Thread.Sleep(...) with Timers. 所以我不确定如何用计时器替换任何Thread.Sleep(...)

Any clues? 有什么线索吗?

Clarification 澄清

I do not want to exit the Run() method :) I'm very happy to keep looping forever. 我不想退出Run()方法:)我很高兴能永远循环下去。 What I'm stuck with, is replacing the standard Thread.Sleep(...) call (which blocks the thread) and replace that with a Timer , which most people suggest. 我所坚持的是,替换标准的Thread.Sleep(...)调用(阻止线程),并用大多数人建议的Timer替换它。

Update 更新

Please do not link or suggest that I should use cancelSource.Token.WaitHandle.WaitOne(); 请不要链接或建议我使用cancelSource.Token.WaitHandle.WaitOne(); as a solution. 作为解决方案。 That is not what I'm trying to achieve here. 那不是我要在这里实现的目标。 Please note the post title! 请注意帖子标题!

I figure that if you want to solve this situation the way you outline here you will need a WaitHandle AND a Timer. 我认为,如果要按此处概述的方式解决此问题,则需要一个WaitHandle和一个Timer。

The short answer is here below. 简短的答案在下面。 The long answer became a blog post: HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep 长答案成了一篇博客文章: 如何在Thread.Sleep上使用Timer和EventWaitHandle在WorkerRole中等待

I used an EventWaitHandle along with the Timer and came up with this solution: 我将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()
    {
        // [...]
    }
}

And here is the waiter class: 这是服务生类:

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;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM