1

ここで質問の前に質問しました。マルチスレッドに関するこの質問/回答を読み、それらの解決策を知っています。しかし、今日、私は新しい問題を抱えています。コマンドを使用している場合(または元のコードにアクセスして管理および変更できる場合)、上記の回答で提案されているasync-decoratorが機能します。しかし、MVC自体が新しいスレッドを作成する場合、何ができるでしょうか。たとえば、カスタムロールプロバイダー(で動作DbContext)があり、次のエラーが発生します:

DbContextが破棄されたため、操作を完了できません。

そして、ここにスタックトレースがあります:

[InvalidOperationException:DbContextが破棄されたため、操作を完了できません。]

System.Data.Entity.Internal.InternalContext.CheckContextNotDisposed()+67

System.Data.Entity.Internal.LazyInternalContext.InitializeContext()+34

System.Data.Entity.Internal.Linq.DbQueryProvider.Execute(式)+22

System.Linq.Queryable.Any(IQueryable 1 source, Expression1述語)+265

MyProject.MyRoleProvider.IsUserInRole(String username、String roleName)in..。

System.Web.Security.Roles.IsUserInRole(String username、String roleName)+263

MyProject.MyPrincipal.IsInRole(String role)in..。

System.Linq.Enumerable.Any(IEnumerable 1 source, Func2述語)+146

System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext)+200

System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext)+159

System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext、IList`1フィルター、ActionDescriptor actionDescriptor)+96

System.Web.Mvc.Async。<> c__DisplayClass25.b__1e(AsyncCallback asyncCallback、Object asyncState)+446

System.Web.Mvc.Async。WrappedAsyncResult`1.Begin(AsyncCallbackコールバック、オブジェクト状態、Int32タイムアウト)+130

System.Web.Mvc.Async。AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext、String actionName、AsyncCallbackコールバック、オブジェクト状態)+302

System.Web.Mvc。<> c__DisplayClass1d.b__17(AsyncCallback asyncCallback、Object asyncState)+30

System.Web.Mvc.Async。WrappedAsyncResult`1.Begin(AsyncCallbackコールバック、オブジェクト状態、Int32タイムアウト)+130

System.Web.Mvc。Controller.BeginExecuteCore(AsyncCallbackコールバック、オブジェクト状態)+382

System.Web.Mvc.Async。WrappedAsyncResult`1.Begin(AsyncCallbackコールバック、オブジェクト状態、Int32タイムアウト)+130

System.Web.Mvc。Controller.BeginExecute(RequestContext requestContext、AsyncCallbackコールバック、オブジェクト状態)+317

System.Web.Mvc.Controller.System.Web.Mvc.Async。IAsyncController.BeginExecute(RequestContext requestContext、AsyncCallbackコールバック、オブジェクト状態)+15

System.Web.Mvc。<> c__DisplayClass8.b__2(AsyncCallback asyncCallback、Object asyncState)+71

System.Web.Mvc.Async。WrappedAsyncResult`1.Begin(AsyncCallbackコールバック、オブジェクト状態、Int32タイムアウト)+130

System.Web.Mvc。MvcHandler.BeginProcessRequest(HttpContextBase httpContext、AsyncCallbackコールバック、オブジェクト状態)+249

System.Web.Mvc。MvcHandler.BeginProcessRequest(HttpContext httpContext、AsyncCallbackコールバック、オブジェクト状態)+50

System.Web.Mvc.MvcHandler.System.Web。IHttpAsyncHandler.BeginProcessRequest(HttpContextコンテキスト、AsyncCallback cb、オブジェクトextraData)+16

System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+301

System.Web.HttpApplication.ExecuteStep(IExecutionStep step、Boolean&completedSynchronously)+155

ご覧のとおり、MyProject.MyRoleProvider.IsUserInRole非同期で呼び出されましたが、これは開始しませんでした。MVC自体による非同期の呼び出しです。だから私はそれを制御することはできません。私のプロバイダーコンストラクターは次のとおりです。

public MyRoleProvider(){_context = MyIoCWrapper.GetService(); }

MyRoleProviderインスタンス化されたときHttpContextはnullではなく、IsInRole呼び出されたときHttpContextはnullのようです。新しいライフスコープを開始したい場合は、1回だけ使用され、MVCが新しいスレッドを開始した場合は、新しいスレッドも使用されDbContextます。私は解決策を見つけるのに混乱しました。誰かいますか?すべてのバックグラウンドスレッドの新しいライフスコープを開始するにはどうすればよいですか?それらを開始するか、MVCが開始しますか?

4

1 に答える 1

1

あなたの問題は、実際にはコントローラーを非同期で実行することとは関係ありませんが、オブジェクトの有効期間を制御する一般的な問題です。

MyRoleProviderアプリケーションの web.config に登録したか、コードで登録した可能性があります。いずれにせよ、これMyRoleProviderはシングルトンであり、アプリケーションの存続期間中にそのクラスのインスタンスが 1 つだけ存在します。

ただし、ライフスタイルが短い (Web リクエストごとまたはあなたの場合はハイブリッド) にMyRoleProvider依存します。良い。この行は、それをキャッシュしていることを示しているようです。DbContextDbContextMyRoleProverDbContext_context = MyIoCWrapper.GetService();DbContext

この場合DbContext、各メソッド呼び出しでインスタンスを解決する必要があります。代わりに、次のIsUserInRoleようになります。

public bool IsUserInRole(String username, String roleName)
{
    var context = MyIoCWrapper.GetService();
    return context.Roles
        .Any(r => r.Name == roleName && r.User.Name == username);
}
于 2012-11-04T18:28:51.830 に答える