Merge pull request #6 from specklesystems/dim/dev

Updates
This commit is contained in:
Dimitrie Stefanescu
2020-10-16 00:19:33 +01:00
committed by GitHub
6 changed files with 50 additions and 47 deletions
@@ -20,13 +20,11 @@ namespace GrasshopperAsyncComponent
public override GH_Exposure Exposure => GH_Exposure.hidden;
Action<string, GH_RuntimeMessageLevel> ReportError;
List<(string, GH_RuntimeMessageLevel)> Errors;
//List<(string, GH_RuntimeMessageLevel)> Errors;
Action<string, double> ReportProgress;
ConcurrentDictionary<string, double> ProgressReports;
public ConcurrentDictionary<string, double> ProgressReports;
Action Done;
@@ -36,7 +34,7 @@ namespace GrasshopperAsyncComponent
bool SetData = false;
List<WorkerInstance> Workers;
public List<WorkerInstance> Workers;
List<Task> Tasks;
@@ -56,29 +54,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) =>
{
@@ -86,8 +62,6 @@ namespace GrasshopperAsyncComponent
if (!DisplayProgressTimer.Enabled) DisplayProgressTimer.Start();
};
ReportError = (error, type) => Errors?.Add((error, type));
Done = () =>
{
State++;
@@ -105,7 +79,6 @@ namespace GrasshopperAsyncComponent
}
};
Errors = new List<(string, GH_RuntimeMessageLevel)>();
ProgressReports = new ConcurrentDictionary<string, double>();
Workers = new List<WorkerInstance>();
@@ -113,6 +86,30 @@ namespace GrasshopperAsyncComponent
Tasks = new List<Task>();
}
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;
@@ -121,7 +118,6 @@ namespace GrasshopperAsyncComponent
CancelationSources.Clear();
Workers.Clear();
Errors.Clear();
ProgressReports.Clear();
Tasks.Clear();
@@ -175,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);
@@ -199,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();
@@ -14,6 +14,12 @@ namespace GrasshopperAsyncComponent
/// </summary>
public abstract class WorkerInstance
{
/// <summary>
/// The parent component. Useful for passing state back to the host component.
/// </summary>
public GH_Component Parent { get; set; }
/// <summary>
/// This token is set by the parent <see cref="GH_AsyncComponent"/>.
/// </summary>
@@ -24,6 +30,11 @@ namespace GrasshopperAsyncComponent
/// </summary>
public string Id { get; set; }
protected WorkerInstance(GH_Component _parent)
{
Parent = _parent;
}
/// <summary>
/// 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.
/// </summary>
@@ -35,9 +46,8 @@ namespace GrasshopperAsyncComponent
/// <b>Make sure you always check as frequently as you can if <see cref="WorkerInstance.CancellationToken"/> is cancelled. For an example, see the <see cref="GrasshopperAsyncComponent.SampleImplementations.PrimeCalculatorWorker"/>.</b>
/// </summary>
/// <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, double> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done);
public abstract void DoWork(Action<string, double> ReportProgress, 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>
@@ -78,8 +78,7 @@
</Target>
-->
<PropertyGroup>
<PostBuildEvent>Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha"
Erase "$(TargetPath)"</PostBuildEvent>
<PostBuildEvent>Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha"</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<FallbackCulture>en-US</FallbackCulture>
@@ -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("")]
@@ -38,7 +38,9 @@ namespace GrasshopperAsyncComponent.SampleImplementations
int TheNthPrime { get; set; } = 100;
long ThePrime { get; set; } = -1;
public override void DoWork(Action<string, double> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done)
public PrimeCalculatorWorker() : base(null) { }
public override void DoWork(Action<string, double> ReportProgress, Action Done)
{
// 👉 Checking for cancellation!
if (CancellationToken.IsCancellationRequested) return;
@@ -36,7 +36,9 @@ namespace GrasshopperAsyncComponent.SampleImplementations
{
int MaxIterations { get; set; } = 100;
public override void DoWork(Action<string, double> ReportProgress, Action<string, GH_RuntimeMessageLevel> ReportError, Action Done)
public UselessCyclesWorker() : base(null) { }
public override void DoWork(Action<string, double> ReportProgress, Action Done)
{
// Checking for cancellation
if (CancellationToken.IsCancellationRequested) return;