feat(cancellation): exposes task cancellation method

This commit is contained in:
Dimitrie Stefanescu
2021-04-03 17:10:36 +01:00
parent b7e57b1ec8
commit c314fc5834
5 changed files with 61 additions and 7 deletions
@@ -86,6 +86,24 @@ namespace GrasshopperAsyncComponent
Tasks = new List<Task>();
}
public void RequestCancellation()
{
foreach(var token in CancellationSources)
{
token.Cancel();
}
CancellationSources.Clear();
Workers.Clear();
ProgressReports.Clear();
Tasks.Clear();
Interlocked.Exchange(ref SetData, 0);
Message = "Done";
OnDisplayExpired(true);
}
public virtual void DisplayProgress(object sender, System.Timers.ElapsedEventArgs e)
{
if (Workers.Count == 0)
@@ -4,7 +4,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{695D2B91-DDB6-416E-8A99-DDE6253DA7AA}</ProjectGuid>
<ProjectGuid>{114D5E49-AC13-47F7-A70E-B4289579F4E3}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GrasshopperAsyncComponent</RootNamespace>
@@ -6,6 +6,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GrasshopperAsyncComponent;
using System.Windows.Forms;
namespace GrasshopperAsyncComponentDemo.SampleImplementations
{
@@ -30,7 +31,15 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddNumberParameter("Output", "O", "The n-th prime number.", GH_ParamAccess.item);
}
protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
{
base.AppendAdditionalComponentMenuItems(menu);
Menu_AppendItem(menu, "Cancel", (s, e) =>
{
this.RequestCancellation();
});
}
}
@@ -44,7 +53,7 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
public override void DoWork(Action<string, double> ReportProgress, Action Done)
{
// 👉 Checking for cancellation!
if (CancellationToken.IsCancellationRequested) return;
if (CancellationToken.IsCancellationRequested) { Done(); return; }
int count = 0;
long a = 2;
@@ -53,14 +62,14 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
while (count < TheNthPrime)
{
// 👉 Checking for cancellation!
if (CancellationToken.IsCancellationRequested) return;
if (CancellationToken.IsCancellationRequested) { Done(); return; }
long b = 2;
int prime = 1;// to check if found a prime
while (b * b <= a)
{
// 👉 Checking for cancellation!
if (CancellationToken.IsCancellationRequested) return;
if (CancellationToken.IsCancellationRequested) { Done(); return; }
if (a % b == 0)
{
@@ -98,7 +107,7 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
public override void SetData(IGH_DataAccess DA)
{
// 👉 Checking for cancellation!
if (CancellationToken.IsCancellationRequested) return;
if (CancellationToken.IsCancellationRequested) { return; }
DA.SetData(0, ThePrime);
}
@@ -6,6 +6,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GrasshopperAsyncComponent;
using System.Windows.Forms;
namespace GrasshopperAsyncComponentDemo.SampleImplementations
{
@@ -31,6 +32,15 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
{
pManager.AddTextParameter("Output", "O", "Nothing really interesting.", GH_ParamAccess.item);
}
protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
{
base.AppendAdditionalComponentMenuItems(menu);
Menu_AppendItem(menu, "Cancel", (s, e) =>
{
this.RequestCancellation();
});
}
}
public class UselessCyclesWorker : WorkerInstance
@@ -42,7 +52,7 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
public override void DoWork(Action<string, double> ReportProgress, Action Done)
{
// Checking for cancellation
if (CancellationToken.IsCancellationRequested) return;
if (CancellationToken.IsCancellationRequested) { Done(); return; }
for (int i = 0; i <= MaxIterations; i++)
{
@@ -53,7 +63,7 @@ namespace GrasshopperAsyncComponentDemo.SampleImplementations
ReportProgress(Id, ((double)(i + 1) / (double)MaxIterations));
// Checking for cancellation
if (CancellationToken.IsCancellationRequested) return;
if (CancellationToken.IsCancellationRequested) { Done(); return; }
}
Done();
+17
View File
@@ -46,6 +46,23 @@ Q: Does this component use all my cores? A: OH YES. It goes WROOOM.
![image](https://user-images.githubusercontent.com/7696515/95597125-29310900-0a46-11eb-99ce-663b34506a7a.png)
Q: Can I cancel a stuff that's in progress?
A: Yes. The `GH_AsyncComponent` class now exposes the `RequestCancellation()` method, which you can invoke from a custom menu action, or however you want. Note, to properly handle this and ensure the component's inner flow state is properly reset, when respecting the cancellation in your component, you should call the `Done()` function before returning from `DoWork()`. E.g.:
```cs
public override void DoWork(Action<string, double> ReportProgress, Action Done)
{
// note: call done from inside DoWork(), then return abruptly.
if (CancellationToken.IsCancellationRequested) { Done(); return; }
// more code
}
```
### Debugging
Quite easy: