En comparación con el código anterior para la clase RulyCanceler , quería ejecutar código usando CancellationTokenSource
.
¿Cómo lo uso como se menciona en los tokens de cancelación , es decir, sin lanzar / capturar una excepción? ¿Puedo usar la IsCancellationRequested
propiedad?
Intenté usarlo así:
cancelToken.ThrowIfCancellationRequested();
y
try
{
new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
pero esto dio un error en tiempo de ejecución cancelToken.ThrowIfCancellationRequested();
en el método 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:
El código que ejecuté con éxito captó la OperationCanceledException en el nuevo hilo:
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();
}
}
}
}
CancellationTokenSource
con métodos asíncronos, métodos de ejecución prolongada con sondeo y uso de una devolución de llamada.Respuestas:
Puede implementar su método de trabajo de la siguiente manera:
Eso es. Siempre debe manejar la cancelación usted mismo: salga del método cuando sea el momento adecuado para salir (para que su trabajo y datos estén en un estado consistente)
ACTUALIZACIÓN: Prefiero no escribir
while (!cancelToken.IsCancellationRequested)
porque a menudo hay pocos puntos de salida donde puede dejar de ejecutar de forma segura en el cuerpo del bucle, y el bucle generalmente tiene alguna condición lógica para salir (iterar sobre todos los elementos de la colección, etc.). Así que creo que es mejor no mezclar esas condiciones, ya que tienen una intención diferente.Nota de advertencia sobre cómo evitar
CancellationToken.ThrowIfCancellationRequested()
:Comentario en cuestión de Eamon Nerbonne :
fuente
@ BrainSlugs83
No debe confiar ciegamente en todo lo publicado en stackoverflow. El comentario en el código de Jens es incorrecto, el parámetro no controla si se lanzan excepciones o no.
MSDN tiene muy claro lo que controla ese parámetro, ¿lo ha leído? http://msdn.microsoft.com/en-us/library/dd321703(v=vs.110).aspx
El nombre de la variable también es incorrecto porque se llama a Cancel,
CancellationTokenSource
no al token en sí, y la fuente cambia el estado de cada token que administra.fuente
Puede crear una tarea con token de cancelación, cuando la aplicación vaya al fondo, puede cancelar este token.
Puede hacer esto en PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle
Otra solución es el temporizador de usuario en Xamarin.Forms, detener el temporizador cuando la aplicación vaya al fondo https://xamarinhelp.com/xamarin-forms-timer/
fuente
Usted puede utilizar
ThrowIfCancellationRequested
sin manipular la excepción!El uso de
ThrowIfCancellationRequested
está destinado a usarse desde dentro de aTask
(no aThread
). Cuando se usa dentro de aTask
, no tiene que manejar la excepción usted mismo (y obtiene el error de Excepción no controlada). Dará como resultado dejar elTask
, y laTask.IsCancelled
propiedad será True. No se necesita manejo de excepciones.En su caso específico, cambie
Thread
a aTask
.fuente
t.Start()
y noTask.Run()
?Debe pasar el
CancellationToken
a la tarea, que monitoreará periódicamente el token para ver si se solicita la cancelación.En este caso, la operación finalizará cuando se solicite la cancelación y
Task
tendrá unRanToCompletion
estado. Si desea que se le reconozca que su tarea ha sido cancelada , debe usarThrowIfCancellationRequested
para lanzar unaOperationCanceledException
excepción.Espero que esto ayude a comprender mejor.
fuente