From ed41f2967a343e6ce1a999bf6e743d0dbdba205e Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Wed, 14 Oct 2020 13:31:29 +0100 Subject: [PATCH 1/4] feat(progress display): makes the progress display function overridable --- .../Base/GH_AsyncComponent.cs | 49 ++++++++++--------- .../GrasshopperAsyncComponent.csproj | 3 +- .../Properties/AssemblyInfo.cs | 2 +- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs index 3eee2bb..6af661d 100644 --- a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs +++ b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs @@ -56,29 +56,7 @@ namespace GrasshopperAsyncComponent { DisplayProgressTimer = new Timer(333) { AutoReset = false }; - DisplayProgressTimer.Elapsed += (s, e) => - { - if (Workers.Count == 0) return; - if (Workers.Count == 1) - { - Message = ProgressReports.Values.Last().ToString("0.00%"); - } - else - { - double total = 0; - foreach (var kvp in ProgressReports) - { - total += kvp.Value; - } - - Message = (total / Workers.Count).ToString("0.00%"); - } - - Rhino.RhinoApp.InvokeOnUiThread((Action)delegate - { - OnDisplayExpired(true); - }); - }; + DisplayProgressTimer.Elapsed += DisplayProgress; ReportProgress = (id, value) => { @@ -113,6 +91,31 @@ namespace GrasshopperAsyncComponent Tasks = new List(); } + public virtual void DisplayProgress(object sender, System.Timers.ElapsedEventArgs e) + { + if (Workers.Count == 0) return; + if (Workers.Count == 1) + { + Message = ProgressReports.Values.Last().ToString("0.00%"); + } + else + { + double total = 0; + foreach (var kvp in ProgressReports) + { + total += kvp.Value; + } + + Message = (total / Workers.Count).ToString("0.00%"); + } + + Rhino.RhinoApp.InvokeOnUiThread((Action)delegate + { + OnDisplayExpired(true); + }); + } + + protected override void BeforeSolveInstance() { if (State != 0 && SetData) return; diff --git a/GrasshopperAsyncComponent/GrasshopperAsyncComponent.csproj b/GrasshopperAsyncComponent/GrasshopperAsyncComponent.csproj index 30e8f2c..9b3b252 100644 --- a/GrasshopperAsyncComponent/GrasshopperAsyncComponent.csproj +++ b/GrasshopperAsyncComponent/GrasshopperAsyncComponent.csproj @@ -78,8 +78,7 @@ --> - Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha" -Erase "$(TargetPath)" + Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha" en-US diff --git a/GrasshopperAsyncComponent/Properties/AssemblyInfo.cs b/GrasshopperAsyncComponent/Properties/AssemblyInfo.cs index 3764cb5..bc7322f 100644 --- a/GrasshopperAsyncComponent/Properties/AssemblyInfo.cs +++ b/GrasshopperAsyncComponent/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTitle("GrasshopperAsyncComponent")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] +[assembly: AssemblyCompany("Aec systems")] [assembly: AssemblyProduct("GrasshopperAsyncComponent")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] From 26c86a361d2359d9ab37d7177334e64c1b1dc828 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Wed, 14 Oct 2020 13:52:23 +0100 Subject: [PATCH 2/4] feat(fields): made some progress report related props public --- GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs index 6af661d..091e9dd 100644 --- a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs +++ b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs @@ -26,7 +26,7 @@ namespace GrasshopperAsyncComponent Action ReportProgress; - ConcurrentDictionary ProgressReports; + public ConcurrentDictionary ProgressReports; Action Done; @@ -36,7 +36,7 @@ namespace GrasshopperAsyncComponent bool SetData = false; - List Workers; + public List Workers; List Tasks; From 381579d1f95188d9d652841c25942b4b1fbc5908 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 16 Oct 2020 00:07:08 +0100 Subject: [PATCH 3/4] feat(workers): now possible to pass the parent component to the worker --- .../Base/GH_AsyncComponent.cs | 1 - GrasshopperAsyncComponent/Base/WorkerInstance.cs | 15 +++++++++++++-- .../Sample_PrimeCalculatorAsyncComponent.cs | 2 ++ .../Sample_UslessCyclesComponent.cs | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs index 091e9dd..a4b0079 100644 --- a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs +++ b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs @@ -115,7 +115,6 @@ namespace GrasshopperAsyncComponent }); } - protected override void BeforeSolveInstance() { if (State != 0 && SetData) return; diff --git a/GrasshopperAsyncComponent/Base/WorkerInstance.cs b/GrasshopperAsyncComponent/Base/WorkerInstance.cs index 41bf0bb..fb5d705 100644 --- a/GrasshopperAsyncComponent/Base/WorkerInstance.cs +++ b/GrasshopperAsyncComponent/Base/WorkerInstance.cs @@ -14,6 +14,12 @@ namespace GrasshopperAsyncComponent /// public abstract class WorkerInstance { + + /// + /// The parent component. Useful for passing state back to the host component. + /// + public GH_Component Parent { get; set; } + /// /// This token is set by the parent . /// @@ -24,6 +30,11 @@ namespace GrasshopperAsyncComponent /// public string Id { get; set; } + protected WorkerInstance(GH_Component _parent) + { + Parent = _parent; + } + /// /// This is a "factory" method. It should return a fresh instance of this class, but with all the necessary state that you might have passed on directly from your component. /// @@ -35,9 +46,9 @@ namespace GrasshopperAsyncComponent /// Make sure you always check as frequently as you can if is cancelled. For an example, see the . /// /// Call this to report progress up to the parent component. - /// Call this to report errors up to the parent component. + /// Call this to report errors up to the parent component. /// Call this when everything is done. It will tell the parent component that you're ready to . - public abstract void DoWork(Action ReportProgress, Action ReportError, Action Done); + public abstract void DoWork(Action ReportProgress, Action ReportMessage, Action Done); /// /// Write your data setting logic here. Do not call this function directly from this class. It will be invoked by the parent after you've called `Done` in the function. diff --git a/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs b/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs index 1d91333..ca485ac 100644 --- a/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs +++ b/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs @@ -38,6 +38,8 @@ namespace GrasshopperAsyncComponent.SampleImplementations int TheNthPrime { get; set; } = 100; long ThePrime { get; set; } = -1; + public PrimeCalculatorWorker() : base(null) { } + public override void DoWork(Action ReportProgress, Action ReportError, Action Done) { // 👉 Checking for cancellation! diff --git a/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs b/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs index f3204fa..5b94b8f 100644 --- a/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs +++ b/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs @@ -36,6 +36,8 @@ namespace GrasshopperAsyncComponent.SampleImplementations { int MaxIterations { get; set; } = 100; + public UselessCyclesWorker() : base(null) { } + public override void DoWork(Action ReportProgress, Action ReportError, Action Done) { // Checking for cancellation From 88cfab29105e9a43b292abd55603836817aae6b2 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 16 Oct 2020 00:17:02 +0100 Subject: [PATCH 4/4] feat(messages): removes the ReportError action (pass in parent comp) easier to pass in the parent comp and directly set runtime messages on it BREAKING CHANGE: signature for the DoWork function changes --- .../Base/GH_AsyncComponent.cs | 18 +++--------------- .../Base/WorkerInstance.cs | 3 +-- .../Sample_PrimeCalculatorAsyncComponent.cs | 2 +- .../Sample_UslessCyclesComponent.cs | 2 +- 4 files changed, 6 insertions(+), 19 deletions(-) diff --git a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs index a4b0079..444b08c 100644 --- a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs +++ b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs @@ -20,9 +20,7 @@ namespace GrasshopperAsyncComponent public override GH_Exposure Exposure => GH_Exposure.hidden; - Action ReportError; - - List<(string, GH_RuntimeMessageLevel)> Errors; + //List<(string, GH_RuntimeMessageLevel)> Errors; Action ReportProgress; @@ -64,8 +62,6 @@ namespace GrasshopperAsyncComponent if (!DisplayProgressTimer.Enabled) DisplayProgressTimer.Start(); }; - ReportError = (error, type) => Errors?.Add((error, type)); - Done = () => { State++; @@ -83,7 +79,6 @@ namespace GrasshopperAsyncComponent } }; - Errors = new List<(string, GH_RuntimeMessageLevel)>(); ProgressReports = new ConcurrentDictionary(); Workers = new List(); @@ -123,7 +118,6 @@ namespace GrasshopperAsyncComponent CancelationSources.Clear(); Workers.Clear(); - Errors.Clear(); ProgressReports.Clear(); Tasks.Clear(); @@ -177,11 +171,11 @@ namespace GrasshopperAsyncComponent Task CurrentRun; if (TaskCreationOptions != null) { - CurrentRun = new Task(() => CurrentWorker.DoWork(ReportProgress, ReportError, Done), tokenSource.Token, (TaskCreationOptions)TaskCreationOptions); + CurrentRun = new Task(() => CurrentWorker.DoWork(ReportProgress, Done), tokenSource.Token, (TaskCreationOptions)TaskCreationOptions); } else { - CurrentRun = new Task(() => CurrentWorker.DoWork(ReportProgress, ReportError, Done), tokenSource.Token); + CurrentRun = new Task(() => CurrentWorker.DoWork(ReportProgress, Done), tokenSource.Token); } // Add cancelation source to our bag CancelationSources.Add(tokenSource); @@ -201,14 +195,8 @@ namespace GrasshopperAsyncComponent if (State == 0) { - foreach (var (message, type) in Errors) - { - AddRuntimeMessage(type, message); - } - CancelationSources.Clear(); Workers.Clear(); - Errors.Clear(); ProgressReports.Clear(); Tasks.Clear(); diff --git a/GrasshopperAsyncComponent/Base/WorkerInstance.cs b/GrasshopperAsyncComponent/Base/WorkerInstance.cs index fb5d705..aec07a6 100644 --- a/GrasshopperAsyncComponent/Base/WorkerInstance.cs +++ b/GrasshopperAsyncComponent/Base/WorkerInstance.cs @@ -46,9 +46,8 @@ namespace GrasshopperAsyncComponent /// Make sure you always check as frequently as you can if is cancelled. For an example, see the . /// /// Call this to report progress up to the parent component. - /// Call this to report errors up to the parent component. /// Call this when everything is done. It will tell the parent component that you're ready to . - public abstract void DoWork(Action ReportProgress, Action ReportMessage, Action Done); + public abstract void DoWork(Action ReportProgress, Action Done); /// /// Write your data setting logic here. Do not call this function directly from this class. It will be invoked by the parent after you've called `Done` in the function. diff --git a/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs b/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs index ca485ac..4efe02b 100644 --- a/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs +++ b/GrasshopperAsyncComponent/SampleImplementations/Sample_PrimeCalculatorAsyncComponent.cs @@ -40,7 +40,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations public PrimeCalculatorWorker() : base(null) { } - public override void DoWork(Action ReportProgress, Action ReportError, Action Done) + public override void DoWork(Action ReportProgress, Action Done) { // 👉 Checking for cancellation! if (CancellationToken.IsCancellationRequested) return; diff --git a/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs b/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs index 5b94b8f..0e04ab0 100644 --- a/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs +++ b/GrasshopperAsyncComponent/SampleImplementations/Sample_UslessCyclesComponent.cs @@ -38,7 +38,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations public UselessCyclesWorker() : base(null) { } - public override void DoWork(Action ReportProgress, Action ReportError, Action Done) + public override void DoWork(Action ReportProgress, Action Done) { // Checking for cancellation if (CancellationToken.IsCancellationRequested) return;