2

Timerの代わりにThread.Sleep(...)aを使用するように言っている人々の例はたくさんありAzure Worker Roleます。それには問題はありません。

私が理解するのに苦労しているのは、これをコーディングする方法です。

現在、私は次の(疑似コード)を持っています

_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()メソッドに 1 回入り、 DoesStuff(tm).. 正常に .. タイマーが開始され (たとえば .. 30 秒間隔で)、そのメソッドが終了します。

Run()次に、そのループ内にあるmain メソッド .. に戻ります。そのため、タイマーが起動するのを待つ代わりに、すぐに戻ってきてメソッドに再び入ります。DoWork()

Thread.Sleep(...)そのため、いずれかをタイマーに置き換える方法がわかりません。

手がかりはありますか?

明確化

メソッドを終了したくありませんRun():)永遠にループし続けることができてとてもうれしいです。私が立ち往生しているのは、標準のThread.Sleep(...)呼び出し(スレッドをブロックする)を置き換えTimer、それをほとんどの人が提案する に置き換えることです。

アップデート

私が解決策として使用すべきだとリンクしたり提案したりしないでくださいcancelSource.Token.WaitHandle.WaitOne();。それは私がここで達成しようとしていることではありません。投稿タイトルに注目!

4

1 に答える 1

6

ここで概説した方法でこの状況を解決したい場合は、WaitHandle と Timer が必要になると思います。

簡単な答えは以下にあります。長い答えはブログ投稿になりました: HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep

タイマーと共に EventWaitHandle を使用して、この解決策を思いつきました。

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;
        }
    }
}
于 2013-02-06T22:26:26.510 に答える