RulyCanceler 클래스 에 대한 이전 코드와 비교 하여 CancellationTokenSource
.
취소 토큰 에서 언급 한대로 예외를 던지거나 잡지 않고 어떻게 사용합니까? IsCancellationRequested
부동산을 사용할 수 있습니까 ?
나는 이것을 다음과 같이 사용하려고 시도했다.
cancelToken.ThrowIfCancellationRequested();
과
try
{
new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
그러나 이것은 cancelToken.ThrowIfCancellationRequested();
메소드에서 런타임 오류를 제공 했습니다 Work(CancellationToken cancelToken)
.
System.OperationCanceledException was unhandled
Message=The operation was canceled.
Source=mscorlib
StackTrace:
at System.Threading.CancellationToken.ThrowIfCancellationRequested()
at _7CancellationTokens.Token.Work(CancellationToken cancelToken) in C:\xxx\Token.cs:line 33
at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:\xxx\Token.cs:line 22
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
성공적으로 실행 한 코드는 새 스레드에서 OperationCanceledException을 포착했습니다.
using System;
using System.Threading;
namespace _7CancellationTokens
{
internal class Token
{
private static void Main()
{
var cancelSource = new CancellationTokenSource();
new Thread(() =>
{
try
{
Work(cancelSource.Token); //).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
}).Start();
Thread.Sleep(1000);
cancelSource.Cancel(); // Safely cancel worker.
Console.ReadLine();
}
private static void Work(CancellationToken cancelToken)
{
while (true)
{
Console.Write("345");
cancelToken.ThrowIfCancellationRequested();
}
}
}
}
답변
다음과 같이 작업 방법을 구현할 수 있습니다.
private static void Work(CancellationToken cancelToken)
{
while (true)
{
if(cancelToken.IsCancellationRequested)
{
return;
}
Console.Write("345");
}
}
그게 다야. 취소는 항상 혼자서 처리해야합니다. 종료하기에 적절한시기가되면 메소드를 종료하여 작업과 데이터가 일관된 상태에 있도록합니다.
업데이트 : 나는 while (!cancelToken.IsCancellationRequested)
종종 루프 본문에서 안전하게 실행을 멈출 수있는 출구 지점이 거의 없기 때문에 쓰기를 선호하지 않으며 , 루프는 일반적으로 종료 할 논리적 조건이 있습니다 (컬렉션의 모든 항목에 대해 반복). 그래서 저는 의도가 다르기 때문에 그 조건을 혼합하지 않는 것이 좋습니다.
피에 대한주의 사항 CancellationToken.ThrowIfCancellationRequested()
:
문제의 코멘트 에 의해 에이 몬 Nerbonne :
… 이 답변이 말했듯이 출구에
ThrowIfCancellationRequested
대한IsCancellationRequested
일련 의 검사로 정상적으로 대체 됩니다. 그러나 이것은 단순한 구현 세부 사항이 아닙니다. 관찰 가능한 동작에 영향을줍니다 : 작업은 더 이상 취소 된 상태로 끝나지 않고RanToCompletion
. 그리고 그것은 명시적인 상태 검사뿐만 아니라 더 미묘하게ContinueWith
는TaskContinuationOptions
사용되는 것에 따라 예를 들어 작업 체인에 영향을 줄 수 있습니다 . 피하는ThrowIfCancellationRequested
것은 위험한 조언 이라고 말하고 싶습니다 .
답변
안녕하세요.
stackoverflow에 게시 된 모든 것을 맹목적으로 신뢰해서는 안됩니다. Jens 코드의 주석이 올바르지 않습니다. 매개 변수는 예외 발생 여부를 제어하지 않습니다.
MSDN은 그 매개 변수가 무엇을 제어하는지 매우 명확합니다. 읽어 보셨습니까?
http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx
경우
throwOnFirstException
에 해당하는 예외 즉시 처리되지 나머지 콜백 및 캔슬 조작을 방지하는 취소 호출 밖으로 전달한다. 경우
throwOnFirstException
거짓,이 오버로드는 던져 예외를 집계한다AggregateException
예외를 던지는 하나의 콜백이 실행되는 다른 등록 된 콜백을 방지하지 않도록.
CancellationTokenSource
토큰 자체가 아닌 Cancel이 호출되고 소스가 관리하는 각 토큰의 상태를 변경 하기 때문에 변수 이름도 잘못되었습니다 .
답변
취소 토큰으로 Task를 생성 할 수 있으며, 백그라운드로 이동할 때이 토큰을 취소 할 수 있습니다.
PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle 에서이 작업을 수행 할 수 있습니다.
var cancelToken = new CancellationTokenSource();
Task.Factory.StartNew(async () => {
await Task.Delay(10000);
// call web API
}, cancelToken.Token);
//this stops the Task:
cancelToken.Cancel(false);
Anther 솔루션은 Xamarin.Forms의 사용자 타이머, 앱이 백그라운드로 이동할 때 타이머 중지
https://xamarinhelp.com/xamarin-forms-timer/
답변
예외를 처리하지 않고 사용할 수 있습니다ThrowIfCancellationRequested
!
의 사용은 (가 아님 ) ThrowIfCancellationRequested
내에서 사용됩니다 . 에서 사용 하면 예외를 직접 처리 할 필요가 없습니다 (그리고 처리되지 않은 예외 오류가 발생 함). 을 떠나게 되고 속성은 True가됩니다. 예외 처리가 필요하지 않습니다.Task
Thread
Task
Task
Task.IsCancelled
특정 경우에는 Thread
을 Task
.
Task t = null;
try
{
t = Task.Run(() => Work(cancelSource.Token), cancelSource.Token);
}
if (t.IsCancelled)
{
Console.WriteLine("Canceled!");
}
답변
CancellationToken
취소 요청 여부를 확인하기 위해 주기적으로 토큰을 모니터링하는 태스크에을 전달해야합니다 .
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
Task task = Task.Run(() => {
while(!token.IsCancellationRequested) {
Console.Write("*");
Thread.Sleep(1000);
}
}, token);
Console.WriteLine("Press enter to stop the task");
Console.ReadLine();
cancellationTokenSource.Cancel();
이 경우 취소가 요청되면 작업이 종료 Task
되고 RanToCompletion
상태가됩니다. 당신이 인정을 받으려면 귀하의 작업이 취소되었습니다 , 당신은 사용할 필요가 ThrowIfCancellationRequested
던져 OperationCanceledException
예외.
Task task = Task.Run(() =>
{
while (!token.IsCancellationRequested) {
Console.Write("*");
Thread.Sleep(1000);
}
token.ThrowIfCancellationRequested();
}, token)
.ContinueWith(t =>
{
t.Exception?.Handle(e => true);
Console.WriteLine("You have canceled the task");
},TaskContinuationOptions.OnlyOnCanceled);
Console.WriteLine("Press enter to stop the task");
Console.ReadLine();
cancellationTokenSource.Cancel();
task.Wait();
이것이 더 잘 이해하는 데 도움이되기를 바랍니다.