[英]How to use the CancellationToken property?
与前面的RulyCanceler 类代码相比,我想使用CancellationTokenSource
运行代码。
我如何像Cancellation Tokens 中提到的那样使用它,即不抛出/捕获异常? 我可以使用IsCancellationRequested
属性吗?
我试图像这样使用它:
cancelToken.ThrowIfCancellationRequested();
和
try
{
new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
但这在cancelToken.ThrowIfCancellationRequested();
上给出了一个运行时错误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()
注意事项:
...替换
ThrowIfCancellationRequested
用一堆检查IsCancellationRequested
优雅退出,正如这个答案所说。 但这不仅仅是一个实现细节; 影响可观察行为:任务将不再以取消状态结束,而是以RanToCompletion
。 这不仅会影响显式状态检查,而且会更巧妙地影响任务链接,例如ContinueWith
,具体取决于所使用的TaskContinuationOptions
。 我会说避免ThrowIfCancellationRequested
是危险的建议。
与前面的RulyCanceler类代码相比,我想使用CancellationTokenSource
运行代码。
如取消令牌中所述,如何使用它,即不引发/捕捉异常? 我可以使用IsCancellationRequested
属性吗?
我试图这样使用它:
cancelToken.ThrowIfCancellationRequested();
和
try
{
new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
但这给了cancelToken.ThrowIfCancellationRequested();
一个运行时错误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();
}
}
}
}
您可以使用取消令牌创建任务,当您应用转到后台时,您可以取消此令牌。
您可以在 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);
花药解决方案是 Xamarin.Forms 中的用户计时器,当应用程序转到后台时停止计时器https://xamarinhelp.com/xamarin-forms-timer/
您可以使用ThrowIfCancellationRequested
而不处理异常!
ThrowIfCancellationRequested
的使用意味着在Task
(而不是Thread
)中使用。 在Task
,您不必自己处理异常(并获得未处理的异常错误)。 这将导致离开Task
,并且Task.IsCancelled
属性将为 True。 不需要异常处理。
在您的特定情况下,将Thread
更改为Task
。
Task t = null;
try
{
t = Task.Run(() => Work(cancelSource.Token), cancelSource.Token);
}
if (t.IsCancelled)
{
Console.WriteLine("Canceled!");
}
您必须将CancellationToken
传递给 Task,它会定期监视令牌以查看是否请求取消。
// CancellationTokenSource provides the token and have authority to cancel the token
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
// Task need to be cancelled with CancellationToken
Task task = Task.Run(async () => {
while(!token.IsCancellationRequested) {
Console.Write("*");
await Task.Delay(1000);
}
}, token);
Console.WriteLine("Press enter to stop the task");
Console.ReadLine();
cancellationTokenSource.Cancel();
在这种情况下,操作将在请求取消时结束, Task
将具有RanToCompletion
状态。 如果您想确认您的任务已被取消,您必须使用ThrowIfCancellationRequested
抛出OperationCanceledException
异常。
Task task = Task.Run(async () =>
{
while (!token.IsCancellationRequested) {
Console.Write("*");
await Task.Delay(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();
希望这有助于更好地理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.