52

新しい .NET 4 System.Runtime.Caching MemoryCache を使用している MVC 3 アプリケーションに問題があります。一見予測できない時間が経過した後、キャッシュが停止し、空のように動作することに気付きました。ASP.NET MVC のテスト ビューから直接取得した次のコードについて考えてみましょう。

MemoryCache.Default.Set("myname","fred", new CacheItemPolicy() { SlidingExpiration = new TimeSpan(0,5,0) });
Response.Write(MemoryCache.Default["myname"]);

それが機能している場合、予想通り「fred」が出力されます。ただし、問題が発生し始めるとSet()、 の値MemoryCache.Default["myname"]は null になります。Response.Write()行にブレークポイントを設定し、イミディエイト ウィンドウを使用してキャッシュを直接設定して読み取ることで、これを証明できます。設定されず、null のままです。それを再び機能させる唯一の方法は、AppDomain のリサイクルを引き起こすことです。

興味深いことに、アプリが正常に動作しているときに、Response.Write()回線を中断して実行すると、問題が発生する可能性がありますMemoryCache.Default.Dispose()。その後、MemoryCache.Default 自体は null ではありませんが (これはなぜでしょうか?)、設定されたものは保存されません。エラーは発生しませんが、何も保存されません。

誰でもこれを確認して説明できますか? 私が発見したと信じているように、アプリが単独で動作しなくなると、何かが DisposingMemoryCache.Defaultになりますが、それは私ではありません!


アップデート

さて、私は今、この問題にうんざりしています! CLRProfiler は MVC 3 では動作しないようです。SciTech の CLR ツールは優れていましたが、RedGate ANTS も同様でした。しかし、彼らが私に言ったのは、MemoryCache オブジェクトが何かによって破棄されているということだけでした。また、(OutputCacheAttribute で指定された) キャッシュする必要がある私のページの PartialView が数分後にキャッシュを停止することを (タイムスタンプの印刷を介して) 証明しました。ページへの呼び出しごとに更新が開始されます。環境を明確にするために、Win 7 Ultimate を実行している開発ワークステーションの IIS 7.5 サーバーで直接実行しています。上記のメモリ ツールは、プレイ中のオブジェクトに関して、約 9 MB のメモリしか使用していないことを示唆しています。

必死になって、キャッシングコードを変更して、最初にアンビエント HttpContext を検索してフックし、そのキャッシング機能が利用可能な場合はそれを使用しました。初期のテストはこれが信頼できることを示していますが、厄介なハックのように感じます.

MemoryCache と OutputCache は MVC 3 での動作が保証されていないと感じています...

4

5 に答える 5

70

というわけで、お知らせです。これを調べたところ、はい、これは .NET 4 のバグです。

幸いなことに、この問題は .NET 4.5 で修正されているため、可能であれば、インストールを .NET 4.5 に更新してください。

もう 1 つの良いニュースは、この修正が .NET 4 にバックポートされ、QFE (クイック修正...適用する 1 回限りの修正) #578315 として利用できるようになることです。ほんの数日前にバックポート/修正されたので、できるだけ早くリリースする必要があります。正確な日付を取得しようとしますが、すぐです。

もう 1 つの良いニュースは、QFE の前に .NET 4 でこれに対する回避策があることです。回避策は奇妙ですが、ブロックを解除できます。

using (ExecutionContext.SuppressFlow())     {
          // Create memory cache instance under disabled execution context flow
         return new YourCacheThing.GeneralMemoryCache(…);
}

お役に立てれば。

更新: ホットフィックスはhttp://support.microsoft.com/kb/2828843で、こちらからリクエストできます: https://support.microsoft.com/contactus/emailcontact.aspx?scid=sw;%5BLN%5D; 1422

于 2013-03-30T07:07:03.527 に答える
6

同じ問題があります。しばらくするとキャッシュが破棄されたことを確認しました。プライベート フィールド _disposed が 1 になりました。私のコードには cache.Dispose への呼び出しがないと確信しています。しかし、Reflector を使用して MemoryCache のコードを見たところ、コンストラクターで 2 つのイベントをサブスクライブしていることがわかります。

domain.DomainUnload += eventHandler;
domain.UnhandledException += exceptionEventHandler;

private void OnAppDomainUnload(object unusedObject, EventArgs unusedEventArgs)
{
  this.Dispose();
}

private void OnUnhandledException(object sender, UnhandledExceptionEventArgs eventArgs)
{
  if (!eventArgs.IsTerminating)
    return;
  this.Dispose();
}

これらのイベント ハンドラーは両方とも Dispose を呼び出します。IIS でドメインをリサイクルした後、ドメインのアンロードが発生する可能性がありますが、キャッシュはメモリに保持されます (可能かどうかはわかりません)。

于 2013-03-04T14:15:43.997 に答える
3

私も全く同じ症状を経験しています。最終的に、代わりに System.Web.Cache クラスを使用し、HttpContext.Cache にフックすることになりました。過去3日間、完全に機能しています..

于 2012-11-21T21:38:13.980 に答える
2

同じ問題に関連するこれらのリンクも参照してください。

統合パイプライン モードの WebApp で使用すると、PollingInterval の後に MemoryCache が破棄される

http://connect.microsoft.com/VisualStudio/feedback/details/764911/memorycache-gets-disposed-after-pollinginterval-when-used-in-webapp-in-integrated-pipeline-mode

MemoryCache は魔法のように Disposed 状態になります

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/1233ffb3-6480-431b-94ca-1190f96cf5f6

于 2013-03-22T03:17:34.653 に答える
1

メモリ制限に達すると、MemoryCacheアイテムが自動的に削除されます。これはあなたの場合に発生する可能性があります。キャッシュに多くのアイテムがありますか?

設定で制限を制御できます。デフォルトでは、使用可能なメモリに基づいて最適化されます。

確かに呼び出すDisposeと、インスタンスの動作が停止しMemoryCacheます。これは、破棄の準備ができているすべての管理されていないリソースをクリーンアップするためです。Disposeを使用する予定がない場合にのみ呼び出してくださいMemoryCache。あなたがそれを呼び出す場合を除いて、これはあなたの場合の問題である必要はないと思います。

于 2011-09-14T21:17:34.820 に答える