4

リクエストの最後に破棄する必要のある単純なクラスがいくつかあります。

そのために、のイベントDisposeからそれらのオブジェクトのメソッドを呼び出します。Application_EndRequestGlobal.asax

これは「私のマシンでは正常に動作します」が、本番サーバーで問題がCannot access a disposed object.発生します。これは、一部のMVCヘルパーで発生します。

Application_EndRequestは、リクエストの最後にトリガーされるように見えました。そうではありませんか?オブジェクトを破棄するために使用する必要がある別のイベントはありますか?

4

3 に答える 3

5

アプリケーションプールの問題-可能性が高い

使い捨てオブジェクトはリクエストにバインドされているのではなく、アプリ全体にバインドされていると思われます(リクエストごとにインスタンス化される場合がありますが、一部の共有リソースを使用している場合があります)。アプリケーションを開発環境でテストしている限り、期待どおりに動作するように見えますが、本番環境に置くとすぐに問題が発生します。これは、アプリケーションプールに問題がある可能性があることを示しています

IIS Webアプリケーションプール機能は、実際にはHttpApplicationアプリケーションのいくつかのインスタンスをインスタンス化し、それらはすべて共通の使い捨てリソースを共有する場合があります。それが使い捨てオブジェクトの場合であり、それを共有している場合は、スレッドセーフではない可能性があります。共有リソースの使用をスレッドセーフな操作にラップしない場合も同じです。

そのため、あるリクエストの進行中に別のリクエストが開始され、最初のリクエストがオブジェクトを破棄し、2番目のプロセスがまだそれを使用している場合があります。

より多くの情報は常に役に立ちます

使い捨てのオブジェクト/リソースの性質と、それをアプリケーションでどのように使用しているかを説明していただければ、さらに便利になります。しかし、それまでの間、アプリケーションプールとその処理について説明している私のブログ投稿を読むことができます。それ自体は使い捨てのオブジェクトではありませんが、それでもすべての情報が非常に有用で役立つ場合があります。

于 2012-10-19T08:54:24.947 に答える
2

コントローラ内で使用するリクエストごとにオブジェクトの使い捨てが必要な場合は、Application_BeginRequestおよびApplication_EndRequestを使用する代わりに、コントローラのライフサイクルハンドラを使用することをお勧めします。次の例を参照してください。

コントローラー:

public class BaseController : Controller
{
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        this.HttpContext.Items["MyDisposableObject"] = new MyDisposableObject();
    }

    protected override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        base.OnResultExecuted(filterContext);

        if (this.HttpContext.Items.Contains("MyDisposableObject"))
        {
            var myDisposableObject = 
                    this.HttpContext.Items["MyDisposableObject"] as IDisposable;

            if (myDisposableObject != null)
            {
                myDisposableObject.Dispose();
            }
        }
    }
}

IDisposableオブジェクト:

public sealed class MyDisposableObject : IDisposable
{
    private bool disposed;

    public void Dispose()
    {
        if (!this.disposed)
        {
            // Dispose all managed 
            // and unmanaged resources. 

            // Note disposing has been done.
            this.disposed = true;
        }
    }
}
于 2012-10-15T06:58:36.417 に答える
0

オブジェクトのスコープがコントローラ レベルに設定されている場合は、DisposeメソッドをオーバーライドしてControllerそれらのオブジェクトを破棄できます。

protected override void Dispose(bool disposing)
{
  if(disposing)
  {
    // dispose the objects here
  }

  base.Dispose(disposing);
}

アプリケーションで DI フレームワーク (Ninject など) を使用している場合は、そのジョブを委任できます。

リクエストの最後にオブジェクトを破棄する代わりに、オブジェクトが破棄usingされるように、この方法でアクセスする場所にステートメントでラップすることもできます。

于 2012-10-15T15:45:19.743 に答える