5

ユーザーがすべてのミルク ジョッキを監視できるアプリケーションがあるとします。ミルクジャグはすべて、ある時点で期限切れになります。

すべてのミルク ジャグを監視して、「isExpired」プロパティが true か false かを確認したいと考えています。

プロパティを更新するために、timerjob のようなものを使用して、時々すべてのジャグを反復処理する必要がありますか? ジャグの有効期限が切れたときにすぐにフィードバックが必要な場合はどうすればよいですか? これを安価/効率的にするために、.NET/C# の世界で利用できるツールは何ですか?

ジャグの有効期限が切れたら、最終的に signalR のようなものを使用して、通知を Web クライアントにプッシュします。

==

これに 2 つの質問を詰め込んで申し訳ありませんが、明らかに重要なのは、ユーザーが水差しを見ているときに通知を送信することだけです。では、ユーザーのセッションが生きている間だけ実行されるタイマージョブは機能するでしょうか? ここでのヒント/推奨される読書は素晴らしいでしょう。

4

3 に答える 3

4

水差しの有効期限が切れたときにすぐに通知が必要な場合は、次の操作を実行できます。

Scan the list of jugs and find the one with the earliest expiration date
Set a timer to expire at that date/time.
When the timer expires, remove that jug from the list.
Scan the list of jugs to find any other jugs that expire at this time.
Send notifications for all the expired jugs.
Go to step 1.

このアルゴリズムにはいくつかの問題があります。

  • 水差しを追加する場合は、その有効期限が現在の最も早い有効期限よりも前であるかどうかを確認する必要があります。その場合、現在の水差しの有効期限のタイマーをリセットする必要があります。
  • 同様に、リストから水差しを削除した場合、それが有効期限を待っている水差しかどうかを確認する必要があります。もしそうなら、あなたは新しい最も古いジャグを見つけて、タイマーをリセットしなければなりません.
  • 水差しの非常に大きなリストをスキャンすると、費用がかかる可能性がありますが、水差しの有効期限が切れたときにのみ実行する必要があります.

リストを並べ替えることで、リストをスキャンする必要がなくなります。次に、最も早い有効期限が常にリストの一番上にあることがわかります。新しいジャグを追加するときは、有効期限までに挿入するだけです。二分探索を使用して、挿入する場所を決定できます。

または、優先キュー (バイナリ ヒープまたはスキップ リスト) を使用して、有効期限ごとに水差しを保存することもできます。どのデータ構造を使用するかは、アイテムの数と更新頻度によって異なります。ジャグが多く、頻繁にアクセスするほど、効率的なデータ構造に注意を払う必要があります。

このアプローチの優れた点は、水差しを期限切れにする必要がある場合にのみタイマーが作動することです。あなたは決して投票しません。

.NET で次のようなワンショット タイマーを作成するのは簡単です。

TimeSpan expirationDelay = jug.ExpirationDateTime - DateTime.Now;

System.Threading.Timer jugTimer = new System.Threading.Timer(
    JugExpirationCallback, null, expirationDelay, TimeSpan.FromMilliseconds(-1));

コンストラクターの最後のパラメーターは、定期的なタイマーではなく、一度起動して終了するように指示します。その後、タイマーのChangeメソッドを呼び出して、次の水差しのタイマーを更新できます。

の計算ではexpirationDelay夏時間が考慮されないことに注意してください。DateTimeそれを行う場合は、計算を行う前に値を UTC に変換する必要があります。または、WaitableTimerを使用してそれを行うことができます。この記事の最後に、WaitableTimer ソースへのリンクがあります。

コメント後の追加情報

あなたのコメントの後、ログインしているユーザーに期限切れのジャグを通知したいのではないかと思います。おそらく、ログインしているユーザーごとに 1 つの水差し (有効期限が最も早いもの) を含むコレクション (リストまたは優先キュー) を使用します。ユーザーのアイテムの有効期限が切れると、データベース クエリを実行して、そのユーザーの次に有効期限が切れるアイテムを取得し、それをリストに追加できます。もちろん、これは、予想されるユーザーの数、各ユーザーの水差しの数、期限切れの頻度によって異なります。

それらをすべてメモリに保持しようとすることもできますが、更新を管理する必要があります。つまり、データベースが更新された場合、メモリ内表現も更新する必要があります。ユーザーごとに 1 つだけ保持する場合、その問題は大幅に簡素化されます。また、必要なメモリも大幅に削減されます。

リストへの入力方法に関係なく、基本的な考え方は変わりません。最も早いアイテムが期限切れになるときに起動するように構成されたタイマーを 1 つ作成します。各アイテムの有効期限が切れたら、次のアイテムのタイマーをリセットします。

リストにアイテムを追加する方法は、「単なる詳細」です。あなたのアプリケーションについて十分な知識がないため、これ以上具体的な推奨事項を作成することはできません。

于 2013-03-28T23:38:16.703 に答える
1

最も簡単な解決策は、タイマー ( http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx ) を使用し、タイマーが切れるたびにイベントをスローすることです。タイマーは、ユーザーが見ているかどうかに基づいて設定/リセットできます。サーバーでイベントがスローされたら、SignalR を使用して、クライアントで関連するメソッドを呼び出したり、ユーザーに通知したりできます。

于 2013-03-28T23:16:02.500 に答える
0

sortedlistを使用してミルクジャグを保持すると、1 つだけチェックする必要があります (または、失敗するまでチェックしますが、通常は 1 つ)。次に、ティックで残りの時間差を取得し、それがデフォルト値 (30 秒?) を下回っている場合は、タイミング間隔を短くすることができます。

また、アドバイスの言葉はプロパティを更新しませんが、timedate プロパティの有効期限を持ち、「残りの秒数」を要求するか、更新する必要があるものは何でもトラブルを求めています。(プロパティの更新に関するコメントで心配して申し訳ありません)、実際の有効期限が切れたプロパティについては、取得アクションで有効期限を確認するだけで、設定について心配する必要はありません。

はい、アクティブなセッションを確認できます。

于 2013-03-28T22:34:16.343 に答える