web-dev-qa-db-ja.com

MemoryCache Empty:設定後にnullを返します

新しい.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ではありません(これはなぜですか?)が、設定されているものは保存されません。エラーは発生しませんが、何も保存されません。

誰でもこれを確認して説明できますか?私が発見したと思うが、アプリが単独で動作を停止すると、somethingは_MemoryCache.Default_を破棄しますが、それは私ではありません!


[〜#〜] update [〜#〜]

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

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

MemoryCacheとOutputCacheがMVC 3で動作することを保証されていないという感覚を得ています...

51
James McCormack

だから、ここにいくつかのニュースがあります。これを調査しました。はい、これは.NET 4のバグです。

良いニュースは、.NET 4.5で修正されたことです。可能な場合は、インストールを.NET 4.5に更新してください。

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

その他の良いニュースは、QFEの前に.NET 4でこれに対する回避策があることです。回避策は奇妙ですが、ブロックされない可能性があります。

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

お役に立てれば。

更新:修正プログラムは http://support.Microsoft.com/kb/282884 で、ここからリクエストできます: https://support.Microsoft.com/contactus/emailcontact。 aspx?scid = sw;%5BLN%5D; 1422

68
Scott Hanselman

同じ問題があります。しばらくしてキャッシュが破棄されたことを確認します。プライベートフィールド_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でのドメインリサイクルの後、ドメインのアンロードが発生しますが、キャッシュをメモリに保持します(可能な場合はシュアしません)。

6
Dima

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

3
Grant

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

統合パイプラインモードの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が魔法のように破棄状態になる

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

2
Alex Nolasco

MemoryCacheは、メモリ制限に達するとアイテムを自動的に削除します。これはあなたのケースで起こっている可能性があります、キャッシュに多くのアイテムがありますか?

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

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

1
TheCodeKing