2016-08-15 11 views
2

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; 
    } 
} 
} 
+0

나는 낸시 (Nancy)를 알지 못합니다. 그러나 그것은 자신에게 전달되는 토큰이있는 것 같습니다. 하지만 한 가지 토큰 만 검사하도록 제한 할 필요는 없습니다. 전달한 것을 사용할 수 있고 _either_가 설정된 경우 취소 할 수 있습니다. 더 자세한 정보가 필요하면 질문을 개선하여 좋은 [mcve]를 포함시켜야합니다. 특히 문제가있는 것이 무엇인지 명확하게 알 수 있습니다. 위의 코드 예제에서 나는 장애물로 특히 명백하게 보이는 것은 보이지 않습니다. 'CreateLinkedTokenSource()'를 사용하면 한 번에 두 개의 토큰을 단순화 할 수 있습니다. –

+0

두 번째 예제에서 더 명확하게하기 :이 방법이 효과가 있다고 생각했지만 cts.Cancel()을 호출하면 cToken.IsCancellationRequested를 algy.RunAlgorithm (cToken) 내에서 호출하면 cToken 객체가 true를 반환하지 않습니다. – Phrank

+0

_ "cts.Cancel()을 호출하면 cToken 객체가 true를 반환하지 않습니다. cToken.IsCancellatio를 호출하면 내 algy.RunAlgorithm (cT oken)"_ - 그럴 가치가 없습니다. 무슨 일이 일어나는지는 그 행동을 믿을 수있게 재현하는 좋은 [mcve]에 의해 정말로지지 되어야만하는 종류의 주장입니다. 'RunAlgorithm()'에 전달한 것과 동일한 토큰을 취소했다고 생각하는 대신에 두 개의 다른 토큰을 처리하는 것이 훨씬 더 가능성이 높습니다. 그러나 좋은 MCVE가 없으면 문제를 해결하는 방법을 제안 할 수 없습니다. –

답변

0

근무 수정 : 도움에 대한 @ 피터 Duniho에

public class TestModule : NancyModule 
{ 
    static CancellationTokenSource cts = new CancellationTokenSource(); 
    static CancellationToken cToken = cts.Token; 

    public TestModule() 
    { 
     Get["/run", true] = async (parameters, ct) => 
     { 
      Algorithm ag = new Algorithm(); 
      Console.Write("Running Algorithm...\n"); 
      var result = await Task.Run(() => ag.RunAlgorithm(cToken), cToken); 

      return Response.AsText(result.ToString()); 
     }; 

     Get["/cancel"] = _ => 
     { 
      Console.Write("Cancel requested recieved\n"); 
      cts.Cancel(); 
      cts.Dispose(); 
      cts = new CancellationTokenSource(); 
      cToken = cts.Token; 
      return Response.AsText("Cancelled!"); 
     }; 
    } 
} 

감사합니다.