C# 如何使用 CancellationToken 属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15067865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use the CancellationToken property?
提问by Fulproof
Compared to the preceding code for class RulyCanceler, I wanted to run code using CancellationTokenSource
.
与前面的RulyCanceler 类代码相比,我想使用 CancellationTokenSource
.
How do I use it as mentioned in Cancellation Tokens, i.e. without throwing/catching an exception? Can I use the IsCancellationRequested
property?
我如何像Cancellation Tokens 中提到的那样使用它,即不抛出/捕获异常?我可以使用IsCancellationRequested
物业吗?
I attempted to use it like this:
我试图像这样使用它:
cancelToken.ThrowIfCancellationRequested();
and
和
try
{
new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
but this gave a run-time error on cancelToken.ThrowIfCancellationRequested();
in method Work(CancellationToken cancelToken)
:
但这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:
The code that I successfully ran caught the OperationCanceledException in the new thread:
我成功运行的代码在新线程中捕获了 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();
}
}
}
}
采纳答案by Sasha
You can implement your work method as follows:
您可以按如下方式实现您的工作方法:
private static void Work(CancellationToken cancelToken)
{
while (true)
{
if(cancelToken.IsCancellationRequested)
{
return;
}
Console.Write("345");
}
}
That's it. You always need to handle cancellation by yourself - exit from method when it is appropriate time to exit (so that your work and data is in consistent state)
就是这样。你总是需要自己处理取消——在适当的时候退出方法退出(这样你的工作和数据处于一致的状态)
UPDATE:I prefer not writing while (!cancelToken.IsCancellationRequested)
because often there are few exit points where you can stop executing safely across loop body, and loop usually have some logical condition to exit (iterate over all items in collection etc.). So I believe it's better not to mix that conditions as they have different intention.
更新:我不喜欢写,while (!cancelToken.IsCancellationRequested)
因为通常很少有退出点可以在循环体中安全地停止执行,并且循环通常有一些逻辑条件可以退出(迭代集合中的所有项目等)。所以我认为最好不要混合这些条件,因为它们有不同的意图。
Cautionary note about avoiding CancellationToken.ThrowIfCancellationRequested()
:
关于避免的注意事项CancellationToken.ThrowIfCancellationRequested()
:
Comment in questionby Eamon Nerbonne:
... replacing
ThrowIfCancellationRequested
with a bunch of checks forIsCancellationRequested
exits gracefully, as this answer says. But that's not just an implementation detail; that affects observable behavior: the task will no longer end in the cancelled state, but inRanToCompletion
. And that can affect not just explicit state checks, but also, more subtly, task chaining with e.g.ContinueWith
, depending on theTaskContinuationOptions
used. I'd say that avoidingThrowIfCancellationRequested
is dangerous advice.
......正如this answer所说,优雅地替换
ThrowIfCancellationRequested
为一堆IsCancellationRequested
退出检查。但这不仅仅是一个实现细节;这会影响可观察行为:任务将不再以取消状态结束,而是以RanToCompletion
. 这不仅会影响显式状态检查,而且会更微妙地影响使用 eg 的任务链接ContinueWith
,具体取决于所TaskContinuationOptions
使用的。我会说避免ThrowIfCancellationRequested
是危险的建议。
回答by user3285954
@BrainSlugs83
@BrainSlugs83
You shouldn't blindly trust everything posted on stackoverflow. The comment in Jens code is incorrect, the parameter doesn't control whether exceptions are thrown or not.
您不应该盲目相信在 stackoverflow 上发布的所有内容。Jens代码中的注释不正确,参数不控制是否抛出异常。
MSDN is very clear what that parameter controls, have you read it? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx
MSDN很清楚那个参数控制什么,你读过吗? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx
If
throwOnFirstException
is true, an exception will immediately propagate out of the call to Cancel, preventing the remaining callbacks and cancelable operations from being processed. IfthrowOnFirstException
is false, this overload will aggregate any exceptions thrown into anAggregateException
, such that one callback throwing an exception will not prevent other registered callbacks from being executed.
如果
throwOnFirstException
为 true,则异常将立即从对 Cancel 的调用传播出去,从而阻止处理剩余的回调和可取消操作。如果throwOnFirstException
为 false,则此重载会将抛出的任何异常聚合到 中AggregateException
,这样抛出异常的回调不会阻止其他已注册的回调被执行。
The variable name is also wrong because Cancel is called on CancellationTokenSource
not the token itself and the source changes state of each token it manages.
变量名称也是错误的,因为 CancelCancellationTokenSource
不是在令牌本身上调用的,并且源会更改它管理的每个令牌的状态。
回答by Titus
You canuse ThrowIfCancellationRequested
without handling the exception!
您可以使用ThrowIfCancellationRequested
不处理异常!
The use of ThrowIfCancellationRequested
is meant to be used from within a Task
(not a Thread
).
When used within a Task
, you do not have to handle the exception yourself (and get the Unhandled Exception error). It will result in leaving the Task
, and the Task.IsCancelled
property will be True. No exception handling needed.
的使用ThrowIfCancellationRequested
意味着在 a Task
(不是 a Thread
)中使用。在 a 中使用时Task
,您不必自己处理异常(并获得未处理的异常错误)。这将导致离开Task
,并且该Task.IsCancelled
属性将为 True。不需要异常处理。
In your specific case, change the Thread
to a Task
.
在您的特定情况下,将 更改Thread
为 a Task
。
Task t = null;
try
{
t = Task.Run(() => Work(cancelSource.Token), cancelSource.Token);
}
if (t.IsCancelled)
{
Console.WriteLine("Canceled!");
}
回答by Jesse Jiang
You can create a Task with cancellation token, when you app goto background you can cancel this token.
您可以使用取消令牌创建任务,当您应用转到后台时,您可以取消此令牌。
You can do this in PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle
您可以在 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 solution is user Timer in Xamarin.Forms, stop timer when app goto background https://xamarinhelp.com/xamarin-forms-timer/
花药解决方案是 Xamarin.Forms 中的用户计时器,当应用程序转到后台时停止计时器 https://xamarinhelp.com/xamarin-forms-timer/
回答by Mahbubur Rahman
You have to pass the CancellationToken
to the Task, which will periodically monitors the token to see whether cancellation is requested.
您必须将 传递CancellationToken
给 Task,它会定期监视令牌以查看是否请求取消。
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();
In this case, the operation will end when cancellation is requested and the Task
will have a RanToCompletion
state. If you want to be acknowledged that your task has been cancelled, you have to use ThrowIfCancellationRequested
to throw an OperationCanceledException
exception.
在这种情况下,操作将在请求取消时结束,并且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();
Hope this helps to understand better.
希望这有助于更好地理解。