feat(nulls): prevents the flash of null data between component iterations
overrides the ExpireDownStreamObjects() (c) @alanrynne 🙌 fixes #2 and fixes #3 too i think
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Grasshopper.Kernel;
|
||||
@@ -19,12 +20,14 @@ namespace GrasshopperAsyncComponent
|
||||
|
||||
public override GH_Exposure Exposure => GH_Exposure.hidden;
|
||||
|
||||
Action<string> ReportProgress;
|
||||
|
||||
Action<string, GH_RuntimeMessageLevel> ReportError;
|
||||
|
||||
List<(string, GH_RuntimeMessageLevel)> Errors;
|
||||
|
||||
Action<string, double> ReportProgress;
|
||||
|
||||
ConcurrentDictionary<string, double> ProgressReports;
|
||||
|
||||
Action Done;
|
||||
|
||||
Timer DisplayProgressTimer;
|
||||
@@ -55,15 +58,31 @@ 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);
|
||||
});
|
||||
};
|
||||
|
||||
ReportProgress = (progress) =>
|
||||
ReportProgress = (id, value) =>
|
||||
{
|
||||
Message = progress;
|
||||
ProgressReports[id] = value;
|
||||
if (!DisplayProgressTimer.Enabled) DisplayProgressTimer.Start();
|
||||
};
|
||||
|
||||
@@ -87,6 +106,7 @@ namespace GrasshopperAsyncComponent
|
||||
};
|
||||
|
||||
Errors = new List<(string, GH_RuntimeMessageLevel)>();
|
||||
ProgressReports = new ConcurrentDictionary<string, double>();
|
||||
|
||||
Workers = new List<WorkerInstance>();
|
||||
CancelationSources = new List<CancellationTokenSource>();
|
||||
@@ -102,9 +122,12 @@ namespace GrasshopperAsyncComponent
|
||||
CancelationSources.Clear();
|
||||
Workers.Clear();
|
||||
Errors.Clear();
|
||||
ProgressReports.Clear();
|
||||
Tasks.Clear();
|
||||
|
||||
State = 0;
|
||||
|
||||
var test = Params.Output[0].VolatileData;
|
||||
}
|
||||
|
||||
protected override void AfterSolveInstance()
|
||||
@@ -113,9 +136,17 @@ namespace GrasshopperAsyncComponent
|
||||
if (State == 0 && Tasks.Count > 0)
|
||||
{
|
||||
foreach (var task in Tasks) task.Start();
|
||||
var test = Params.Output[0].VolatileData;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExpireDownStreamObjects()
|
||||
{
|
||||
// Prevents the flash of null data until the new solution is ready
|
||||
if (SetData)
|
||||
base.ExpireDownStreamObjects();
|
||||
}
|
||||
|
||||
protected override void SolveInstance(IGH_DataAccess DA)
|
||||
{
|
||||
if (State == 0)
|
||||
@@ -139,7 +170,7 @@ namespace GrasshopperAsyncComponent
|
||||
// Create the task
|
||||
var tokenSource = new CancellationTokenSource();
|
||||
CurrentWorker.CancellationToken = tokenSource.Token;
|
||||
CurrentWorker.Id = DA.Iteration.ToString();
|
||||
CurrentWorker.Id = $"Worker-{DA.Iteration}";
|
||||
|
||||
Task CurrentRun;
|
||||
if (TaskCreationOptions != null)
|
||||
@@ -176,6 +207,7 @@ namespace GrasshopperAsyncComponent
|
||||
CancelationSources.Clear();
|
||||
Workers.Clear();
|
||||
Errors.Clear();
|
||||
ProgressReports.Clear();
|
||||
Tasks.Clear();
|
||||
|
||||
SetData = false;
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ namespace GrasshopperAsyncComponent
|
||||
/// <param name="ReportProgress">Call this to report progress up to the parent component.</param>
|
||||
/// <param name="ReportError">Call this to report errors up to the parent component.</param>
|
||||
/// <param name="Done">Call this when everything is <b>done</b>. It will tell the parent component that you're ready to <see cref="SetData(IGH_DataAccess)"/>.</param>
|
||||
public abstract void DoWork(Action<string> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done);
|
||||
public abstract void DoWork(Action<string, double> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done);
|
||||
|
||||
/// <summary>
|
||||
/// Write your data setting logic here. <b>Do not call this function directly from this class. It will be invoked by the parent <see cref="GH_AsyncComponent"/> after you've called `Done` in the <see cref="DoWork(Action{string}, Action{string, GH_RuntimeMessageLevel}, Action)"/> function.</b>
|
||||
@@ -61,7 +61,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Base\GH_AsyncComponent.cs" />
|
||||
<Compile Include="Info\GrasshopperAsyncComponentInfo.cs" />
|
||||
<Compile Include="Base\IAsyncComponentWorker.cs" />
|
||||
<Compile Include="Base\WorkerInstance.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SampleImplementations\Sample_PrimeCalculatorAsyncComponent.cs" />
|
||||
<Compile Include="SampleImplementations\Sample_UslessCyclesComponent.cs" />
|
||||
|
||||
+6
-5
@@ -16,7 +16,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
|
||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||
|
||||
public Sample_PrimeCalculatorAsyncComponent() : base("Sample Async Component", "PRIME", "Calculates the nth prime number.", "Samples", "Async")
|
||||
public Sample_PrimeCalculatorAsyncComponent() : base("The N-th Prime Calculator", "PRIME", "Calculates the nth prime number.", "Samples", "Async")
|
||||
{
|
||||
BaseWorker = new PrimeCalculatorWorker();
|
||||
}
|
||||
@@ -28,7 +28,8 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
|
||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||
{
|
||||
pManager.AddTextParameter("Output", "O", "The n-th prime number.", GH_ParamAccess.item);
|
||||
pManager.AddNumberParameter("Output", "O", "The n-th prime number.", GH_ParamAccess.item);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
int TheNthPrime { get; set; } = 100;
|
||||
long ThePrime { get; set; } = -1;
|
||||
|
||||
public override void DoWork(Action<string> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done)
|
||||
public override void DoWork(Action<string, double> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done)
|
||||
{
|
||||
// 👉 Checking for cancellation!
|
||||
if (CancellationToken.IsCancellationRequested) return;
|
||||
@@ -66,7 +67,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
b++;
|
||||
}
|
||||
|
||||
ReportProgress(((double)(count) / TheNthPrime).ToString("0.00%"));
|
||||
ReportProgress(Id, ((double)count) / TheNthPrime);
|
||||
|
||||
if (prime > 0)
|
||||
{
|
||||
@@ -96,7 +97,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
// 👉 Checking for cancellation!
|
||||
if (CancellationToken.IsCancellationRequested) return;
|
||||
|
||||
DA.SetData(0, $"Worker {Id}: {TheNthPrime}th prime is: {ThePrime}");
|
||||
DA.SetData(0, ThePrime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
{
|
||||
int MaxIterations { get; set; } = 100;
|
||||
|
||||
public override void DoWork(Action<string> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done)
|
||||
public override void DoWork(Action<string, double> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done)
|
||||
{
|
||||
// Checking for cancellation
|
||||
if (CancellationToken.IsCancellationRequested) return;
|
||||
@@ -47,8 +47,8 @@ namespace GrasshopperAsyncComponent.SampleImplementations
|
||||
for (int j = 0; j <= 100; j++)
|
||||
sw.SpinOnce();
|
||||
|
||||
ReportProgress(((double)(i + 1) / (double)MaxIterations).ToString("0.00%"));
|
||||
|
||||
ReportProgress(Id, ((double)(i + 1) / (double)MaxIterations));
|
||||
|
||||
// Checking for cancellation
|
||||
if (CancellationToken.IsCancellationRequested) return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user