@@ -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("")]
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user