diff --git a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs
index d3bec08..569a7a6 100644
--- a/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs
+++ b/GrasshopperAsyncComponent/Base/GH_AsyncComponent.cs
@@ -65,7 +65,6 @@ namespace GrasshopperAsyncComponent
{
Rhino.RhinoApp.InvokeOnUiThread((Action)delegate
{
- //State = 1;
ExpireSolution(true);
});
}
@@ -116,6 +115,7 @@ namespace GrasshopperAsyncComponent
// Create the task
var tokenSource = new CancellationTokenSource();
CurrentWorker.CancellationToken = tokenSource.Token;
+ CurrentWorker.Id = DA.Iteration.ToString();
var CurrentRun = new Task(() => CurrentWorker.DoWork(ReportProgress, ReportError, Done), tokenSource.Token, TaskCreationOptions.LongRunning);
// Add cancelation source to our bag
@@ -131,6 +131,7 @@ namespace GrasshopperAsyncComponent
Workers[DA.Iteration].SetData(DA);
+ // Note we're decrementing the state here.
if (--State == 0)
{
foreach (var (message, type) in Errors)
diff --git a/GrasshopperAsyncComponent/Base/IAsyncComponentWorker.cs b/GrasshopperAsyncComponent/Base/IAsyncComponentWorker.cs
index ed7f5a4..a470595 100644
--- a/GrasshopperAsyncComponent/Base/IAsyncComponentWorker.cs
+++ b/GrasshopperAsyncComponent/Base/IAsyncComponentWorker.cs
@@ -8,51 +8,48 @@ using System.Threading.Tasks;
namespace GrasshopperAsyncComponent
{
- // TODO: Would an an abstract class be better here?
- public interface IAsyncComponentWorker
- {
-
- ///
- /// This function should return a duplicate instance of your class. Make sure any state is duplicated (or not) properly.
- ///
- ///
- IAsyncComponentWorker GetNewInstance();
-
- ///
- /// Here you can safely set the data of your component, just like you would normally. Important: do not call this method directly! When you are ready, call the provided "Done" action from the DoWork function.
- ///
- ///
- void SetData(IGH_DataAccess DA);
-
- ///
- /// Here you can safely collect the data from your component, just like you would normally. Important: do not call this method directly. It will be invoked by the parent component.
- ///
- /// The magic Data Access class.
- /// The parameters list, in case you need it.
- void CollectData(IGH_DataAccess DA, GH_ComponentParamServer Params);
-
- ///
- /// This where the computation happens. Make sure to check and return if the token is cancelled!
- ///
- /// The cancellation token.
- /// Call this action to report progress. It will be displayed in the component's message bar.
- /// Call this to report a warning or an error.
- /// When you are done computing, call this function to have the parent component invoke the SetData function.
- void DoWork(CancellationToken token, Action ReportProgress, Action ReportError, Action Done);
- }
-
+
+ ///
+ /// A class that holds the actual compute logic and encapsulates the state it needs. Every needs to have one.
+ ///
public abstract class WorkerInstance
{
+ ///
+ /// This token is set by the parent .
+ ///
public CancellationToken CancellationToken { get; set; }
+ ///
+ /// This is set by the parent . You can set it yourself, but it's not really worth it.
+ ///
public string Id { get; set; }
+ ///
+ /// 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.
+ ///
+ ///
public abstract WorkerInstance Duplicate();
-
+
+ ///
+ /// This method is where the actual calculation/computation/heavy lifting should be done.
+ /// 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 ReportError, 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.
+ ///
+ ///
public abstract void SetData(IGH_DataAccess DA);
+ ///
+ /// Write your data collection logic here. Do not call this method directly. It will be invoked by the parent .
+ ///
+ ///
+ ///
public abstract void GetData(IGH_DataAccess DA, GH_ComponentParamServer Params);
}
diff --git a/GrasshopperAsyncComponent/SampleImplementations/SampleAsyncComponent.cs b/GrasshopperAsyncComponent/SampleImplementations/SampleAsyncComponent.cs
index 0e24ccb..05e7703 100644
--- a/GrasshopperAsyncComponent/SampleImplementations/SampleAsyncComponent.cs
+++ b/GrasshopperAsyncComponent/SampleImplementations/SampleAsyncComponent.cs
@@ -87,6 +87,7 @@ namespace GrasshopperAsyncComponent.SampleImplementations
int count = 0;
long a = 2;
+ // Thanks Steak Overflow (TM) https://stackoverflow.com/a/13001749/
while (count < TehNthPrime)
{
if (CancellationToken.IsCancellationRequested) return;