2012-01-04 15 views
2

我有一个NHibernate的动作过滤器,设置了与会议的部署/交易,像这样:为什么我的ActionFilterAttribute的OnActionExecuted方法在异步操作完成之前触发?

public class NHibernateActionAttribute : ActionFilterAttribute 
{ 
    public ISessionFactory SessionFactory { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     // inject nhibernate session into controller 
     // and start transaction 
    } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     // commit or rollback and dispose 
    } 
} 

事件触发,在一个同步操作方法很好,但是当我有一个异步操作,如下面的一个,只要第一个异步方法返回,操作过滤器的OnActionExecuted方法就会触发。

public void SomeOperationAsync(term) 
{ 
    object results = null 
    var worker = new BackgroundWorker(); 

    worker.DoWork += (o,e) => 
    { 
     // Do some lengthy DB query 
     AsyncManager.Parameters["result"] = results; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 

    AsyncManager.OutstandingOperations.Increment(); 
    worker.RunWorkerAsync();   
    // OnActionExecuted fires NOW. 
} 

public ActionResult SomeOperationCompleted(object result) 
{ 
    return Json(result, JsonRequestBehavior.AllowGet); 
    // I would expect OnActionExecuted to fire NOW. 
} 

的问题是,因为我同时异步工作仍然是正在做的OnActionExecuted方法烧制,因为会话已经关闭在后台工作的数据库查询失败。我将如何去解决这个问题?

+0

嗯......你真的应该创造一个背景工作?我还没有使用AsyncController,但我只是假定它会为您处理“异步”方面... – dotjoe 2012-01-04 20:07:56

+0

有几种方法可以做到这一点。如果您使用某种服务或组件来提供自己的BeginWork和EndWork类型的方法,那么您只需将它们挂钩。由于我只是执行一个随机代码块异步,我正在利用BackgroundWorker类来提供异步设施。 – Chris 2012-01-04 20:09:15

+0

哦,所以当你调用Increment()时,它应该阻塞,直到后台工作者代码调用Decrement()?另外,我不认为ISession是线程安全的......那么在这里使用异步的点是什么? – dotjoe 2012-01-04 20:26:18

回答

0

我不知道BackgroundWorker如何在ASP.NET环境中运行,但您可以使用Task类。尝试下面的一个:

public void SomeOperationAsync(term) { 

    AsyncManager.OutstandingOperations.Increment(); 

    Task<object>.Factory.StartNew(() => { 

     object results = null 

     // Do some lengthy DB query 

     return results; 

    }).ContinueWith(t => { 

     AsyncManager.Parameters["result"] = t.Result; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }); 
} 
+0

我只是试着用你的代码,没有骰子。由于ObjectDisposedException(“session closed!”),查询仍然失败。 – Chris 2012-01-04 20:28:05

+0

@克里斯有趣。你在SomeOperationAsync方法里做了什么吗? – tugberk 2012-01-04 20:35:48

+0

不是。我猜这里我的问题的根源是OnActionExecuted不是“异步”的意识。它在第一个方法结束后返回,而不是在AsyncManager执行Completed回调时返回。我不知道为什么,或者如何解决... – Chris 2012-01-04 20:41:41

相关问题