web-dev-qa-db-ja.com

Task.Delayをタイマーとして使用できますか?

1秒ごとにコードを実行したい。現在使用しているコードは次のとおりです。

Task.Run((Action)ExecuteSomething);

そしてExecuteSomething()は以下のように定義されます:

 private void ExecuteSomething()
        {
            Task.Delay(1000).ContinueWith(
               t =>
               {
                   //Do something.

                   ExecuteSomething();
               });
        }

このメソッドはスレッドをブロックしますか?または、C#でTimerクラスを使用する必要がありますか?そして、それは タイマーは実行用に別のスレッドも割り当てます (?)

14
Sharun

MicrosoftのReactive Frameworkがこれに最適です。ビットを取得するには、NuGet "System.Reactive"を実行するだけです。次に、これを行うことができます:

_IDisposable subscription =
    Observable
        .Interval(TimeSpan.FromSeconds(1.0))
        .Subscribe(x => execute());
_

サブスクリプションを停止する場合は、subscription.Dispose()を呼び出します。さらに、Reactive Frameworkは、タスクや基本的なタイマーよりもはるかに強力な機能を提供できます。

5
Enigmativity

Task.Delayは内部でTimerを使用します

Task.DelayTimerを使用するよりもコードを少し明確にできます。そしてasync-awaitは現在のスレッドをブロックしません(通常はUI)。

public async Task ExecuteEverySecond(Action execute)
{
    while(true)
    {
        execute();
        await Task.Delay(1000);
    }
}

ソースコードから: Task.Delay

// on line 5893
// ... and create our timer and make sure that it stays rooted.
if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout
{
    promise.Timer = new Timer(state => ((DelayPromise)state).Complete(), promise, millisecondsDelay, Timeout.Infinite);
    promise.Timer.KeepRootedWhileScheduled();
}

// ...
19
Fabio
static class Helper
{
    public async static Task ExecuteInterval(Action execute, int millisecond, IWorker worker)
    {
        while (worker.Worked)
        {
            execute();

            await Task.Delay(millisecond);
        }
    }
}


interface IWorker
{
    bool Worked { get; }
}
0
nim