Nancy API를 사용하여 C# 응용 프로그램을 작성합니다. 가끔씩 사용자가 취소해야하는 매우 긴 길이의 최적화 알고리즘을 실행하는 비동기 작업이 있습니다. 사이비 코드는 다음과 같이경로 내에서 작업 취소
Get["/algorithm/run/", true] = async (parameters, ct) =>
{
var algy = new Algorithm();
var result = await Task.Run(() => algy.RunAlgorithm(ct), ct);
};
어떻게이 CancellationToken
(CT)을 취소, 또는 알고리즘을 취소하는 새로운 방법을 만들어 가야합니까?
내가 시도 대안은 같은 것입니다 :
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();
};
그러나 경로는 자신의 비동기 작업에 있기 때문에 이것은 분명히 작동하지 않습니다.
나는 기사가 여기에 게시 읽고: 당신이 협력 경로 처리기에서 처리를 취소 할 경우
이 CancellationToken 이렇게 전달 된당신이 결정하는 ct.IsCancellationRequested 속성을 확인할 수 있습니다 언급 http://blog.jonathanchannon.com/2013/08/24/async-route-handling-with-nancy/ . 예를 들어, 내부 오류가 있거나 미들웨어가 요청을 취소하기로 결정하거나 호스트가 종료 된 경우이 등록 정보를 설정할 수 있습니다. 너는 낸시가 오윈 (OWIN)을 준수한다는 것을 알지 못했다면, 오윈 (OWIN) 사양이 나온 이후 꽤 많이 있었다.
스레드를 처리하는 데있어 새로운 도움을 주시면 도움을받을 수 있습니다.
전체 예 :
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;
}
}
}
나는 낸시 (Nancy)를 알지 못합니다. 그러나 그것은 자신에게 전달되는 토큰이있는 것 같습니다. 하지만 한 가지 토큰 만 검사하도록 제한 할 필요는 없습니다. 전달한 것을 사용할 수 있고 _either_가 설정된 경우 취소 할 수 있습니다. 더 자세한 정보가 필요하면 질문을 개선하여 좋은 [mcve]를 포함시켜야합니다. 특히 문제가있는 것이 무엇인지 명확하게 알 수 있습니다. 위의 코드 예제에서 나는 장애물로 특히 명백하게 보이는 것은 보이지 않습니다. 'CreateLinkedTokenSource()'를 사용하면 한 번에 두 개의 토큰을 단순화 할 수 있습니다. –
두 번째 예제에서 더 명확하게하기 :이 방법이 효과가 있다고 생각했지만 cts.Cancel()을 호출하면 cToken.IsCancellationRequested를 algy.RunAlgorithm (cToken) 내에서 호출하면 cToken 객체가 true를 반환하지 않습니다. – Phrank
_ "cts.Cancel()을 호출하면 cToken 객체가 true를 반환하지 않습니다. cToken.IsCancellatio를 호출하면 내 algy.RunAlgorithm (cT oken)"_ - 그럴 가치가 없습니다. 무슨 일이 일어나는지는 그 행동을 믿을 수있게 재현하는 좋은 [mcve]에 의해 정말로지지 되어야만하는 종류의 주장입니다. 'RunAlgorithm()'에 전달한 것과 동일한 토큰을 취소했다고 생각하는 대신에 두 개의 다른 토큰을 처리하는 것이 훨씬 더 가능성이 높습니다. 그러나 좋은 MCVE가 없으면 문제를 해결하는 방법을 제안 할 수 없습니다. –