問題タブ [memorycache]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - AddOrGetExisting は有効期限を考慮しません
(.NET 4.5) MemoryCache を SlidingExpiration と組み合わせて使用しています。
メソッド .AddOrGetExisting() は有効期限を考慮していないようですが、.Get() は考慮していることに気付きました。
単体テスト:
質問:
これは.AddOrGetExisting()の予想される動作ですか?
.Get() にフォールバックし、null の場合は .Add() にフォールバックできます。
ただし、その結果、スレッドセーフを確保するために独自のロックを実装する必要があります。
c# - これは C# の MemoryCache をクリアする良い解決策ですか?
C# での MemoryCache のクリアに関する質問と回答を読みました。次のような多くの推奨事項がありました:1.キャッシュを列挙し、すべてのアイテムを削除します-他の人によると、これは良くありません.列挙子を取得すると全体がロックされ、ドキュメントの一部から引用すると、あらゆる種類の黙示録が発生します. 、見つかりませんでした。警告が表示され、再現できませんでした。とにかく、これは非常に効率的な解決策だとは思いません。
キーを別のコレクションに保存し、それを繰り返して、キャッシュからアイテムを削除します。- これを除けば、あまりスレッド セーフとは言えません。効率的とも言えません。
古いキャッシュを破棄し、新しいキャッシュを作成する - これは良いことのように思えますが、古いキャッシュへの既存の参照が問題を引き起こす可能性があるという明らかな問題が頭に浮かび、いくつかのコメントで指摘されています。もちろん、アクションの順序は重要です。古いものの参照を保存し、古いものの代わりに新しいものを作成し、古いものを破棄する必要があります-誰もがこの小さなニュアンスに気付いていないようです.
ならどうしよう?私の同僚の 1 人が、私の問題に MemoryCache を使用することを提案しました。彼はキャッシュ オブジェクトを別のクラスにラップしました。このクラスには、キーを取得する (必要に応じてデータベースからロードする)、キーを削除する、またはキャッシュをクリアするオプションがあります。 . 最初の 2 つは今のところ重要ではありませんが、3 番目は興味深いものです。これには、「自分の実装以外の MemoryCache オブジェクトへの追加の参照がないことが保証されている」という行に沿って、3 番目のソリューションを使用しました。したがって、関連するコードは次のとおりです。
コンストラクタ:
キャッシュの消去:
_cache はプライベートな MemoryCache オブジェクトです。
これにより、マルチスレッド環境で問題が発生する可能性はありますか? read と dispose を並行して呼び出すことに懸念があります。同時読み取りを許可する何らかのロック メカニズムを実装する必要がありますが、キャッシュのクリア関数は現在の読み取りがキャッシュで終了するまで待機しますか?
はい、これを実装する必要がありますが、それに到達する前にいくつかの洞察を得たいと思います。
ロバート
Vooの答えのEDIT 1: 「ラッパー」(MyCache)の外にいる人は誰も_cacheオブジェクトへの参照を取得しないことが保証されています。私の心配は次のようなものです。
古いキャッシュをまだ使用しているT2スレッドは別として、これは好ましくありませんが、私が住むことができるものは、Getメソッドが破棄された状態で古いキャッシュに何らかの形でアクセスしたり、データなしで新しいキャッシュを読み取ったりする状況がある可能性があります?
次のような GetOrReadFromDb 関数を想像してください。
たとえば、db からの読み取り直後、および _chache[key] 値で戻る前に、読み取りスレッドから制御が奪われ、クリアに渡される可能性があり、それが問題を引き起こす可能性があると思います。それは本当の問題ですか?
c# - Windows アプリケーションの永続メモリ キャッシュ?
Windows フォーム アプリケーションを閉じた後も保持されるメモリ内キャッシュを探しています。これまでのところ、私が検討した唯一のオプションは、アプリケーションを閉じる前に、バイナリ フォーマッタを使用してメモリ キャッシュ オブジェクトをファイルに書き込むことです。
NuGet で使用できる永続メモリ キャッシュはありますか?
編集:「マッピング」テーブルには約 3,000 万行あり、1 時間ごとに約 100,000 回クエリする必要があります。キャッシュを必要とする背後にある考え方は、データベースにクエリが積み重ならないようにすることでした。
マッピング テーブルの構造:
1 時間ごとに解析する約 100,000 のプロファイルがあります。この解析の一環として、郵便番号に対してタイムゾーン オフセットをクエリし、それを使用して時間範囲を計算します。
それを行う最良の方法は何ですか?
c# - Finalizer で MemoryCache を破棄すると AccessViolationException がスローされる
編集 追加の詳細については、質問の下部にある編集メモを参照してください。
元の質問
MemoryCache
内部で .NET クラスのインスタンスを作成して保持する CacheWrapper クラスがあります。
MemoryCache
AppDomain イベントにフックされるため、明示的に破棄されない限り、ガベージ コレクションは行われません。これは、次のコードで確認できます。
この動作のため、私の MemoryCache インスタンスは管理されていないリソースとして扱われるべきだと思います。つまり、CacheWrapper のファイナライザーで確実に破棄されるようにする必要があります (CacheWrapper 自体は Disposable であり、標準の Dispose(bool) パターンに従います)。
ただし、コードが ASP.NET アプリの一部として実行されると、これにより問題が発生することがわかりました。アプリケーション ドメインがアンロードされると、ファイナライザーが CacheWrapper クラスで実行されます。MemoryCache
これにより、インスタンスの破棄が試みられます。ここで問題が発生します。IIS からいくつかの構成情報を読み込もうとしているようですがDispose
、失敗します (おそらくアプリ ドメインをアンロードしている最中なので、よくわかりません。私が持っているスタック ダンプは次のとおりです。
これに対する既知の解決策はありますか?ファイナライザーでを破棄する必要があると考えているのは正しいMemoryCache
ですか?
編集
この記事では、Dan Bryant の回答を検証し、多くの興味深い詳細について説明します。StreamWriter
特に、廃棄時にバッファをフラッシュする必要があるため、私の場合と同様のシナリオに直面するのケースを取り上げています。記事の内容は次のとおりです。
一般に、ファイナライザーは管理対象オブジェクトにアクセスできません。ただし、かなり複雑なソフトウェアには、シャットダウン ロジックのサポートが必要です。Windows.Forms 名前空間は、正常なシャットダウンを開始する Application.Exit でこれを処理します。ライブラリ コンポーネントを設計する場合、既存の論理的に類似した IDisposable と統合されたシャットダウン ロジックをサポートする方法があると便利です (これにより、組み込みの言語サポートなしで IShutdownable インターフェイスを定義する必要がなくなります)。これは通常、IDisposable.Dispose が呼び出された場合は正常なシャットダウンをサポートし、そうでない場合は中止的なシャットダウンをサポートすることによって行われます。ファイナライザーを使用して、可能な限り正常なシャットダウンを実行できればさらに良いでしょう。
マイクロソフトもこの問題に直面しました。StreamWriter クラスは Stream オブジェクトを所有しています。StreamWriter.Close はそのバッファーをフラッシュしてから、Stream.Close を呼び出します。ただし、StreamWriter が閉じられていない場合、そのファイナライザーはそのバッファーをフラッシュできません。Microsoft は StreamWriter にファイナライザーを提供しないことでこの問題を「解決」し、プログラマーがデータの欠落に気付き、エラーを推測できるようにしました。これは、シャットダウン ロジックの必要性を示す完璧な例です。
そうは言っても、WeakReference を使用して「マネージド ファイナライズ」を実装できるはずだと思います。基本的に、オブジェクトが作成されたときに、自分自身への WeakReference といくつかのキューでのファイナライズ アクションをクラスに登録させます。キューはバックグラウンド スレッドまたはタイマーによって監視され、ペアになっている WeakReference が収集されると、適切なアクションが呼び出されます。もちろん、ファイナライズ アクションが誤ってクラス自体を保持して、コレクションが完全に妨げられないように注意する必要があります。
c# - 一定期間、MemoryCache の有効期限を一時停止する方法はありますか?
アプリケーション内でデータをキャッシュするために .NET の MemoryCache クラスを使用しています。ほとんどのアプリケーションのユース ケースで、絶対的および/またはスライド式の有効期限キャッシュ ポリシーが私のアプリケーションに最適です。ただし、特定の期間に、アプリケーションは、アプリケーション データを更新しない長時間実行プロセスを開始する場合があります。通常、このプロセスは非常に長いため、このプロセス中にキャッシュの有効期限が切れて、キャッシュされたデータが掃除されます。これは、データをキャッシュに残しておきたいときです。MemoryCache の期限切れや清掃を一時的に停止する方法はありますか?
すべてのアイテムを破棄して、有効期限ポリシーを 1 つずつ変更することもできますが、キャッシュ内に何百万とは言わないまでも何十万ものアイテムがあることを考えると、それは、パフォーマンスの視点。
アイテムを CacheEntryRemovedCallback のキャッシュに戻すことも考えられますが、それはシステムで作業するのではなく、システムと戦っているように見え、スレッドセーフではありません。
どんなアイデアでも大歓迎です。
c# - C# での MemoryCache の予期しない削除
私の運用サーバーには、頻繁に使用される SQL Server インスタンスと、ac# Windows サービスであるアプリケーションがあります。私のサービスは、さまざまな時間にさまざまなジョブを実行します。24 時間ごとに、さまざまなジョブの進行状況に関する最新情報を提供する電子メールが送信されます。
このコードは、メモリ キャッシュ内のフラグをチェックして、電子メールを送信するかどうかを決定します。コードは次のようになります。
私のメイン ループは約 1 分ごとに null エントリをチェックしているため、大量の電子メールを受信しています。Add が失敗したか、アイテムが削除されたかのように見えますか?
十分なメモリが利用できない場合にアイテムが削除される可能性がある場所を読みました。これが発生した時点で、メンテナンス スクリプトが SQL Server で実行されており、ボックスで使用可能なメモリはほとんどゼロでした。サーバー、chrome、SSMS などで実行していたいくつかのプログラムを閉じたところ、ログ エントリや電子メールがなくなりました。
アイテムの有効期限を明示的に [現在 + 24 時間] に設定しているので、アイテムが 24 時間追加されることを期待しています!
ここでの解決策は何ですか? CacheItemPriority を NotRemoveable に設定し、24 時間後に手動でアイテムを削除する必要がありますか?
キャッシュをどのように使用しているかという点を無効にしますか、または NotRemovable は AbsoluteExpirationDate と連携して機能しますか?
c# - 不必要にキャッシュされるオブジェクトをインスタンス化せずに、MemoryCache を設定するにはどうすればよいですか?
MemoryCacheクラスは、存在する場合は取得し、存在しない場合は追加するスレッドセーフな方法である.AddOrGetExistingというメソッドを公開します。
このメソッドはNULL
、キャッシュされたオブジェクトがまだ存在しない場合に戻ります。キャッシュ内の存在に関するフィードバックをユーザーに提供するため、これの価値を理解していると思います。
私のキャッシュ リゾルバーは次のようになります。
私が達成しようとしているのは、オブジェクトが必要でない限り作成されず、必要な場合は 2 回作成したくないということです。
私が懸念しているのは.Value
、自分のLazy
型の をパラメーターとして渡すと、アイテムがキャッシュにあるかどうかに関係なく、初期化子が呼び出される可能性があることです。ただし、JIT を正しく理解していれば、メソッドのデリゲートは渡され、呼び出されません。
これらの目標を達成するにはどうすればよいですか:
- キャッシュに既に存在する場合は、オブジェクト初期化子を呼び出さないでください
- キャッシュにない場合は、一度だけ呼び出します。
c# - Web API のメモリ キャッシュ
私は自分の Web API でキャッシングを探していました。そこでは、1 つの API メソッド (12 時間に 1 回変更される) の出力を後続の呼び出しに使用できます。その後、SO でこのソリューションを見つけましたが、以下のコードを理解して使用するのが困難です。
以下のコンテキストでこのメソッドを呼び出して使用する方法がわかりませんか? Getメソッドがあります
Get の出力をキャッシュして、他のメソッド GetEmployeeById() または Search() で使用したい