プライベート状態 (ConcurrentDictionary) を定期的に処理する必要があるクラスがあります。私はこれを経由してやっていTask.Factory.StartNew(doStuff)
ます。このタスクはコレクションを変更するため、条件が true になったときに doStuff が 1 回だけ実行されるようにしたいと考えています。実行中の作業は競合状態を無視しても問題ありませんが、冗長なタスクがリソースを占有し、同期を締め出すことはできれば望んでいません。現在、問題なく動作する二重チェック ロックによって制御されていますが、メソッドの最後に追加するのは非常に冗長なコードです。
public void method()
{
...
// do the method related stuff. Upon executing this method, the condition for
// executing the task could become true, so it is appropriate to try to start it,
// even though it is not directly related to the semantics of this method
...
// now see if the task should be run
if (clock.Now > timestamp.Plus(interval) && periodicTask == null)
{
lock (lockObject)
{
if (periodicTask == null)
periodicTask = Task.Factory.StartNew(this.DoStuff);
}
}
}
private void DoStuff()
{
doActualProcessing();
//signal that task is complete
timestamp = clock.Now;
periodicTask = null;
}
このセットアップは、DoStuff が何度も呼び出されるのを防ぐために機能しますが、冗長すぎて少し汚れているように見えます。理想的には、この単一呼び出しロジックをカプセル化して、次のようなことができるようにしたいと考えています。
public void method()
{
// do the method related stuff.
...
// now see if the task should be run
startTaskExactlyOnce(DoStuff);
}
私が見た唯一のオプションは、おそらくLazy<T>
これを達成するために を使用することですが、ここでは適切ではないようです: 1. オブジェクトを初期化していない、タスクを実行している 2. タスクは定期的に実行される期間ごとに 1 回 3. タスクを開始する必要があるだけなのでLazy<t>.Value
、実行を引き起こすために使用するための翻訳はありません。