public async Task <T> Run() { // Determine if experiments should be run. if (!await ShouldExperimentRun()) { // Run the control behavior. return(await Behaviors[0].Behavior()); } if (BeforeRun != null) { await BeforeRun(); } // Randomize ordering... NamedBehavior[] orderedBehaviors; lock (_random) { orderedBehaviors = Behaviors.OrderBy(b => _random.Next()).ToArray(); } var observations = new List <Observation <T> >(); foreach (var behavior in orderedBehaviors) { observations.Add(await Observation <T> .New(behavior.Name, behavior.Behavior, Comparator, Thrown)); } var controlObservation = observations.FirstOrDefault(o => o.Name == ControlExperimentName); var result = new Result <T>(this, observations, controlObservation, Contexts); try { // TODO: Make this Fire and forget so we don't have to wait for this // to complete before we return a result await Scientist.ResultPublisher.Publish(result); } catch (Exception ex) { Thrown(Operation.Publish, ex); } if (ThrowOnMismatches && result.Mismatched) { throw new MismatchException <T>(Name, result); } if (controlObservation.Thrown) { throw controlObservation.Exception; } return(controlObservation.Value); }
public async Task <T> Run() { // Determine if experiments should be run. if (!await ShouldExperimentRun()) { // Run the control behavior. return(await Behaviors[0].Behavior()); } if (BeforeRun != null) { await BeforeRun(); } // Randomize ordering... NamedBehavior[] orderedBehaviors; lock (_random) { orderedBehaviors = Behaviors.OrderBy(b => _random.Next()).ToArray(); } // Break tasks into batches of "ConcurrentTasks" size var observations = new List <Observation <T, TClean> >(); foreach (var behaviors in orderedBehaviors.Chunk(ConcurrentTasks)) { // Run batch of behaviors simultaneously var tasks = behaviors.Select(b => { return(Observation <T, TClean> .New( b.Name, b.Behavior, Comparator, Thrown, Cleaner)); }); // Collect the observations observations.AddRange(await Task.WhenAll(tasks)); } var controlObservation = observations.FirstOrDefault(o => o.Name == ControlExperimentName); var result = new Result <T, TClean>(this, observations, controlObservation, Contexts); try { await Scientist.ResultPublisher.Publish(result); } catch (Exception ex) { Thrown(Operation.Publish, ex); } if (ThrowOnMismatches && result.Mismatched) { throw new MismatchException <T, TClean>(Name, result); } if (controlObservation.Thrown) { throw controlObservation.Exception; } return(controlObservation.Value); }