C# Async Programming – Is It Okay for Async Function to Update a Common Object?

asyncasynchronous-programmingcnet

I have a couple of functions, each function verifies a set of rules and updates a common object. The common object is just a container that holds a list of rules that passed or failed. I would like to implement this as async. Is there any downside to this approach?
Are there any recommendations? The sample code I intend to implement is given below.

using System.Collections.Generic;
using System.Threading.Tasks;

namespace RetailServiceCheck.Core
{
  //This is shared result
  public class Results
  {
    public List<int> FailedRules = new List<int>();

    public List<int> PassedRules = new List<int>();
  }

  //To Check the rules
  public class RuleChecker
  {
     Results ruleResult = null;
     public RuleChecker()
     {
         ruleResult=new Results();
     }

     public Results ValidateRule()
     {
         var ckr1=CheckRule1();
         var ckr2=CheckRule2();
         var ckr3=CheckRule3();
         Task.WaitAll(ckr1, ckr2, ckr3);
         return ruleResult;
     }

     private async Task CheckRule1()
     {
         //Do some rule check and if the based on rule failure or pass
         ruleResult.PassedRules.Add(1);
     }

     private async Task CheckRule2()
     {
         //Do some rule check and if the based on rule failure or pass
         ruleResult.FailedRules.Add(2);
     }

     private async Task CheckRule3()
     {
         //Do some rule check and if the based on rule failure or pass
         ruleResult.PassedRules.Add(3);
     }

    }
   }

Best Answer

Having each async method update a common object risks running into threading/non-deterministic order issues with the results. So rather than have each async method update a common object, have each return a result, then update the results when all have completed:

 public Results ValidateRule()
 {
     var ckr1=CheckRule1();
     var ckr2=CheckRule2();
     var ckr3=CheckRule3();
     Task.WaitAll(ckr1, ckr2, ckr3);
     UpdateRuleResult(ckr1.Result);
     UpdateRuleResult(ckr2.Result);
     UpdateRuleResult(ckr3.Result);
 }

 private void UpdateRuleResult((bool passed, int value))
 {
     if (passed)
     {
         ruleResult.PassedRules.Add(value);
     }
     else
     {
         ruleResult.FailedRules.Add(value);
     }
 }

 private async Task<(bool passed, int value)> CheckRule1()
 {
     //Do some rule check and if the based on rule failure or pass
     return (true, 1);
 }

 etc
Related Topic