これにアプローチできる方法は無数にあります。私が最初に頭に浮かぶのは、バックグラウンドスレッドで開始するStopwatchオブジェクトまたはTimerオブジェクトを使用してから、関心のあるイベントをサブスクライブできるイベントハンドラーを作成することです。イベントが発生すると、ハンドラーが起動し、タイマーを一時停止して経過時間を照会し、それに応じて増分/リセットの決定を行うことができます。
これは、1つの概念の非常に大まかなスケッチにすぎませんが、前進するためのいくつかのアイデアを提供するはずです。幸運を。
上記の@hatchetによるコメントによると、これは、コメントが問題を正確に反映している場合にキャプチャする必要がある「期限切れ」メンバーまたは「スライディングウィンドウ」イベントホライズンのキューのように聞こえ始めます。
編集私は境界線の強迫神経症なので、あなたの元の問題にいくつかの考えを与え、あなたの問題に関連するかもしれないし、関連しないかもしれない概念を思いつきました、しかし少なくとも学術演習のために私は私が何を投稿するつもりですやりました。あなたの元の投稿で私の注意を引いたのは、非常に斬新だと思った、期限切れまたは時限変数の概念でした。あなたの問題は、与えられた間隔が経過したときに特定のことをしたいということを指定しました。
私はそのアイデアを一般的な形に抽象化しようとしました。そのようなアイデアが役立つかもしれないいくつかの方法を考えました。頭に浮かんだアイデアの1つは、ゲーム環境でした。たとえば、メッセージは、「自己破壊」する前の20秒間だけプレーヤーが利用できる場合があります。有効期限の「配管」をタイプに配線することが非常に便利であることがどのように証明されるか想像できました。別のシナリオは、System.Drawing.Imageが一定時間だけ表示されてから消えるCAI環境である可能性があります。これも、有効期限とタイミングコードが組み込まれているシナリオが役立つ場合があります。
したがって、少なくともその多くの概念的な実用性を念頭に置いて、私は仕事に取り掛かりました。私が一緒に投げたもの(そして私はその包括的または完全なふりをしません)は、で表される期限切れタイプのジェネリックですExpiring<T>
。私がまとめたベースラインコードは次のとおりです。
// First stab at an "expiring" type that is only valid for a set interval.
public class Expiring<T>
{
public delegate void ExpiredHandler(object sender, EventArgs e);
public event ExpiredHandler OnExpired;
T instance;
int signaledCount = 0;
long milliseconds = 0;
bool isExpired = false;
bool exceptOnExpiredReference = true;
System.Timers.Timer lapseTimer = new System.Timers.Timer();
public Expiring(T value)
{
instance = value;
}
public virtual void TimerElapsed(object sender, System.Timers.ElapsedEventArgs args)
{
if (OnExpired != null)
{
OnExpired(this, null);
}
isExpired = true;
}
public Expiring(T startValue, long expirationInterval, bool throwElapsedReferenceException):this(startValue)
{
milliseconds = expirationInterval;
lapseTimer.AutoReset = true;
lapseTimer.Interval = milliseconds;
exceptOnExpiredReference = throwElapsedReferenceException;
lapseTimer.Elapsed+=new System.Timers.ElapsedEventHandler(TimerElapsed);
this.Set();
}
public void Set()
{
signaledCount++;
lapseTimer.Stop();
lapseTimer.Start();
}
public T Value
{
get
{
if (!isExpired || !exceptOnExpiredReference)
return instance;
else
throw new InvalidOperationException("Reference to an expired value.");
}
set
{
instance = value;
}
}
}
ここでの考え方は、誰かがを宣言しExpiring<int>
、その初期値、有効期限、および有効期限が経過した後にインスタンスの値にアクセスしようとして例外をスローするかどうかを示す値を指定できるということです。ExpirationIntervalが経過すると、OnExpiredイベントが発生し、宣言者がカスタムイベントハンドラーを指定して、値の有効期限が切れたときにカスタムアクションを提供できるようになります。
呼び出し元が有効期限タイマーをリセットしたい場合は、オブジェクトのSet()メソッドを呼び出すだけで済みます。これはまた、私が最終的に使用しなかった内部の「signaledCount」値をインクリメントしますが、有効期限タイマーがリセットされた回数を決定するという観点から考えていました。有効期限が経過した後にオブジェクトのValueプロパティにアクセスすると、InvalidOperationExceptionがスローされ、「Valuehasexpired」メッセージが表示されます。
残念ながら、このアイデアは実用的というよりも概念的/学術的価値があります。すべての算術演算子をネイティブ値型の実装にオーバーロードすることができれば、はるかに多くの有用性がありますが、C#がこの概念をまったく好まないことをすぐに発見しました(そして、ここでそれを見つけましたここSOの主題に関するかなり広範な投稿)。理想的には、次のようなことを言えるようにしたいと思います。
Expired<Int32> foo = new Expired<Int32>(5,10000,true);
Expired<Int32> bar = new Expired<Int32>(10,10000,true);
Expired<Int32> baz = foo+bar; // can't make that work
この問題は動的型で克服できるという考えもありましたが、現時点では追求しないことにしました。私が打ち出したアイデアは、OPの「時限変数」の概念の一般的な見方に適用されるため、議論のために提供されています。建設的なコメント/批評/洗練が奨励され、歓迎されます。