CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Forum has moved

New location: CSLA .NET forum


CSLA .NET Resources:
  • CSLA .NET forum
  • CSLA .NET home page
  • Wait for object to no longer be busy?

    rated by 0 users
    Not Answered This post has 0 verified answers | 8 Replies | 1 Follower

    Top 10 Contributor
    4,106 Posts
    Andy posted on Tue, Sep 10 2013 7:12 AM

    I feel like I'm missing something simple.  If you have a BO with Async business rules, how do you wait for the object to no longer be busy before carrying on with something else, such as asking the object to save itself?  I would have thought there'd be some method to await the non-busy state, but I can't find anything.  A simple

     

     

     

    while (bo.IsBusy) { }

    doesn't seem to work either (and will burn CPU as well).

    All Replies

    Top 10 Contributor
    2,279 Posts

    Hi,

    You have events like BusyChanged or ValidationCompleted that your code can wait for with a EventWaitHandle.

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 10 Contributor
    4,106 Posts
    Andy replied on Tue, Nov 19 2013 9:26 AM

    JonnyBee:
    You have events like BusyChanged or ValidationCompleted that your code can wait for with a EventWaitHandle.

    Sorry, I guess I'm not clear on what to do.  In an MVC controller if you have an async business rule its possible its still running by the time you get to the action method.  I want to make sure that the controller waits for the object to no longer be busy before checking IsValid or calling Save.  Can you give an example?

    Top 500 Contributor
    35 Posts
    GBE replied on Tue, Nov 19 2013 3:22 PM

    Hi Andy,

    I m stuck with this problem as well.

    Cf.http://forums.lhotka.net/forums/p/11854/54973.aspx#54973 for another thread on that topic. I did not find a correct implementation yet.

    Gilles

    Top 10 Contributor
    2,279 Posts

    Should be as simple as to add this method to your business object:

    public async void CheckAllRulesAndWaitForAllRulesToComplete()
    {
      var tcs = new TaskCompletionSource<bool>();
      // declare event handler
      EventHandler eh = (sender, e) => tcs.SetResult(true);
      // attach to validation complete event
      ValidationComplete += eh;
      // call check rules 
      BusinessRules.CheckRules();
      // wait for tcs to set result (ValidationComplete)
      await tcs.Task;
      // unsubscripbe from event
      ValidationComplete -= eh;
    }

    and call it like this:

    root.CheckAllRulesAndWaitForAllRulesToComplete(); if (!root.IsValid) {   MessageBox.Show("Object has broken rules and can not be saved");   return; } await root.SaveAsync();

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 10 Contributor
    4,106 Posts
    Andy replied on Wed, Nov 20 2013 8:51 AM

    JonnyBee:

    Should be as simple as to add this method to your business object:

    public async void CheckAllRulesAndWaitForAllRulesToComplete() {   var tcs = new TaskCompletionSource<bool>();   // declare event handler   EventHandler eh = (sender, e) => tcs.SetResult(true);   // attach to validation complete event   ValidationComplete += eh;   // call check rules    BusinessRules.CheckRules();   // wait for tcs to set result (ValidationComplete)   await tcs.Task;   // unsubscripbe from event   ValidationComplete -= eh; }

    and call it like this:

    root.CheckAllRulesAndWaitForAllRulesToComplete(); if (!root.IsValid) {   MessageBox.Show("Object has broken rules and can not be saved");   return; } await root.SaveAsync();
    
    

    This is Asp.Net MVC; the rules are run on property set as normal, however since some are async its possible for the BO get to the action method while rules are still running.  If there's a way to do this without having the new method call BusinessRules.CheckRules that would work for me.

    Top 10 Contributor
    2,279 Posts
    JonnyBee replied on Wed, Nov 20 2013 12:50 PM

    The most efficient way is to use (or create your own version) of CslaModelBinder. 

    This use BypassPropertyChecks to load all field values (rather than calling SetProperty and execute rules on a per-property basis) and then call BusinessRules.CheckRules. 

    You should be able to us the code sample I supplied and just extend it a little with a check for BusinessRules.IsRunningRules or BusinessRules.IsRunningAsyncRules and if so call TaskCompletionSource.SetResult and remove the call to BusinessRules.CheckRules. . 

    Jonny Bekkum, Norway CslaContrib Coordinator

    Top 500 Contributor
    35 Posts
    GBE replied on Fri, Nov 22 2013 11:27 AM

    Hi Jonny,

    I do not think that the problem is MVC specific.

    In my case, we are using a 2 tier - Winform - application. We are doing a mass import.

    The import is affecting the firstname & lastname.

    I'm updating my business object, by setting the firstname & lastname properties (mordern way, with managed backend field).

    As a result, this triggers the async rules.

    Thus, when CheckAllRulesAndWaitForAllRulesToComplete() is called, my object is already busy... and is (sometimes) still busy when leaving.

    Do you recommend using LoadProperty ? From my point of view, this would break business object encapsulation...

    Regards,

    Gilles

    Top 10 Contributor
    2,279 Posts

    Hi, 

    I'd rather look at how the ICheckRules interface is implemented and used in Csla.Web.Mvc.CslaModelBinder.  What you need in addition is an overridable method in ICheckRules.CheckRules method and you would be good to go. 

    You _could_ implement this in your own base classes. I will check with Rocky if we can refactor ICheckRules.CheckRules to call an overridable method. 

    Jonny Bekkum, Norway CslaContrib Coordinator

    Page 1 of 1 (9 items) | RSS

    Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
    Email admin@lhotka.net for support.
    Powered by Community Server (Non-Commercial Edition), by Telligent Systems