I am building a C# application using Nancy API. I have an async operation that runs a very length optimization algorithm that needs to be cancelled by the user on occasion. Psuedo-code as follows:
Get["/algorithm/run/", true] = async (parameters, ct) =>
{
var algy = new Algorithm();
var result = await Task.Run(() => algy.RunAlgorithm(ct), ct);
};
How do I go about cancelling the CancellationToken
(ct), or creating a new method of cancelling the algorithm?
An alternative I have tried is something like:
var cts = new CancellationTokenSource();
var cToken = cts.Token;
Get["/algorithm/run/", true] = async (parameters, ct) =>
{
var algy = new Algorithm();
var result = await Task.Run(() => algy.RunAlgorithm(cToken), cToken);
};
Get["/schedule/stop"] = _ =>
{
cts.Cancel();
};
But this obviously does not work since the route is in its own async task.
I have read the article posted here: http://blog.jonathanchannon.com/2013/08/24/async-route-handling-with-nancy/ which mentions:
The CancellationToken is passed in so you can check the ct.IsCancellationRequested property to determine if you want to cooperatively cancel processing in your route handler. This property may be set for example if there is an internal error or if a piece of middleware decides to cancel the request, or the host is shutting down. If you didn't know Nancy is OWIN compliant and has been pretty much since the OWIN specification came out.
Any assistance would be much appreciated as I am new to handling threads.
Full example:
using Nancy;
using Nancy.Hosting.Self;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace NancyApp
{
class Program
{
private static NancyHost NancyHost { get; set; }
private static HttpClient Client { get; set; }
static void Main(string[] args)
{
var configuration = new HostConfiguration()
{
UrlReservations = new UrlReservations() { CreateAutomatically = true }
};
NancyHost = new NancyHost(configuration, new Uri("http://localhost:1234"));
NancyHost.Start();
Client = new HttpClient();
Client.Timeout = new TimeSpan(1, 0, 0);
Client.BaseAddress = new Uri("http://localhost:1234");
Console.WriteLine("Hosting...\n");
Client.GetAsync("http://localhost:1234/run");
System.Threading.Thread.Sleep(5000);
Client.GetAsync("http://localhost:1234/cancel");
Console.ReadLine();
}
}
public class TestModule : NancyModule
{
CancellationTokenSource cts = new CancellationTokenSource();
public TestModule()
{
Get["/run", true] = async (parameters, ct) =>
{
Algorithm ag = new Algorithm();
Console.Write("Running Algorithm...\n");
var result = await Task.Run(() => ag.RunAlgorithm(cts.Token), cts.Token);
return Response.AsText(result.ToString());
};
Get["/cancel"] = _ =>
{
Console.Write("Cancel requested recieved\n");
cts.Cancel();
return Response.AsText("Foo");
};
}
}
class Algorithm
{
public Algorithm()
{
}
public int RunAlgorithm(CancellationToken cToken)
{
int min = Int32.MinValue;
while (min < Int32.MaxValue)
{
if (!cToken.IsCancellationRequested)
{
min++;
}
else
{
Console.Write("IsCancellationRequested true!\n");
cToken.ThrowIfCancellationRequested();
}
}
return min;
}
}
}