2014-02-26 3 views
4

System.Threading.Task.Task를 사용하여 취소 할 수있는 작업 루프를 만들 수 있습니까?취소 가능한 작업 루프를 만드는 방법은 무엇입니까?

흐름이 Task.Delay (X의 밀리 초)로 시작해야 다음 - 정의 작업, 다음 다른 Task.Delay (Y MS)를 계속하고 사용자 정의 작업에서 반복합니다.

var result = Task.Delay(initialDelay) 
       .ContinueWith(t => dostuff..) 
       .ContinueWith what goes here? 

작업을 사용하여 수행 할 수 있습니까?

나는 타이머를 최대 회전 수와 함께 할 수 있지만, 사용하는 작업은 아니, 내가 취소 필요하면 갈 수있는 올바른 방법 것 같다?

답변

9

await이 슈퍼 쉽게 :

public async Task TimedLoop(Action action, 
    CancellationToken token, TimeSpan delay) 
{ 
    while (true) 
    { 
     token.ThrowIfCancellationRequested(); 
     action(); 
     await Task.Delay(delay, token); 
    } 
} 

async없이 (그러나 아직도 단지 TPL을 사용하여)가 조금 지저분합니다. 일반적으로 I 형 Task의 변수 자체를 첨부 연속을함으로써이 문제를 해결한다. 이것은 정상적으로 작동하지만 머리를 감싸는 데는 몇 초가 걸릴 수 있습니다. await이 없으면 대신 Timer을 사용하는 것이 더 쉽습니다.

public Task TimedLoop(Action action, 
    CancellationToken token, TimeSpan delay) 
{ 
    //You can omit these two lines if you want the method to be void. 
    var tcs = new TaskCompletionSource<bool>(); 
    token.Register(() => tcs.SetCanceled()); 

    Task previous = Task.FromResult(true); 
    Action<Task> continuation = null; 
    continuation = t => 
    { 
     previous = previous.ContinueWith(t2 => action(), token) 
      .ContinueWith(t2 => Task.Delay(delay, token), token) 
      .Unwrap() 
      .ContinueWith(t2 => previous.ContinueWith(continuation, token)); 
    }; 
    previous.ContinueWith(continuation, token); 
    return tcs.Task; 
} 
+1

또한 취소 토큰을 '지연'메소드로 전달합니다. –

+0

@EliArbel 편집 됨. – Servy

+0

비동기를 시뮬레이트하기 위해 반복자를 잘못 사용하는 좋은 사례 인 것 같습니다. 그것을위한 도서관이 있습니다. – usr

관련 문제