Estoy jugando con estas tareas de Windows 8 WinRT, y estoy tratando de cancelar una tarea usando el siguiente método, y funciona hasta cierto punto. Se llama al método CancelNotification, lo que te hace pensar que la tarea se canceló, pero en el fondo la tarea sigue ejecutándose, luego, una vez completada, el estado de la tarea siempre se completa y nunca se cancela. ¿Hay alguna manera de detener completamente la tarea cuando se cancela?
private async void TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(CancelNotification);
source.CancelAfter(TimeSpan.FromSeconds(1));
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);
await task;
if (task.IsCompleted)
{
MessageDialog md = new MessageDialog(task.Result.ToString());
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("Uncompleted");
await md.ShowAsync();
}
}
private int slowFunc(int a, int b)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
}
return a + b;
}
private void CancelNotification()
{
}
Respuestas:
Lea sobre Cancelación (que se introdujo en .NET 4.0 y en gran parte no ha cambiado desde entonces) y el Patrón asincrónico basado en tareas , que proporciona pautas sobre cómo usar
CancellationToken
con losasync
métodos.Para resumir, pasa un
CancellationToken
método a cada método que admite la cancelación, y ese método debe verificarlo periódicamente.fuente
CancellationToken
tiene todos los ganchos necesarios para interoperar con sistemas de cancelación personalizados, pero nada puede cancelar un método no cancelable.Wait
oResult
enasync
métodos; siempre debe usarloawait
, lo que desenvuelve la excepción correctamente.CancellationToken.IsCancellationRequested
y en su lugar sugiera lanzar excepciones?O, para evitar modificaciones
slowFunc
(por ejemplo, no tiene acceso al código fuente):También puede usar buenos métodos de extensión desde https://github.com/StephenCleary/AsyncEx y hacer que se vea tan simple como:
fuente
ConfigureAwait
contrario, puede lastimarse en las aplicaciones de interfaz de usuario.using
.Un caso que no se ha cubierto es cómo manejar la cancelación dentro de un método asíncrono. Tomemos, por ejemplo, un caso simple en el que necesita cargar algunos datos en un servicio, hacer que calcule algo y luego devolver algunos resultados.
Si desea admitir la cancelación, la forma más fácil sería pasar un token y verificar si se ha cancelado entre cada llamada al método asincrónico (o usando ContinueWith). Si son llamadas de larga duración, es posible que espere un tiempo para cancelar. Creé un pequeño método auxiliar para fallar tan pronto como lo cancele.
Entonces, para usarlo, simplemente agregue
.WaitOrCancel(token)
a cualquier llamada asíncrona:Tenga en cuenta que esto no detendrá la Tarea que estaba esperando y continuará ejecutándose. Tendrá que usar un mecanismo diferente para detenerlo, como la
CancelAsync
llamada en el ejemplo, o mejor aún, pasar el mismoCancellationToken
alTask
para que pueda manejar la cancelación eventualmente. Intentar abortar el hilo no es recomendable .fuente
UploadDataAsync
puede continuar en segundo plano, pero una vez que se complete, no realizará la llamadaCalculateAsync
porque esa parte ya dejó de esperar). Esto puede o no ser problemático para usted, especialmente si desea volver a intentar la operación. PasarCancellationToken
todo el camino hacia abajo es la opción preferida, cuando sea posible.Solo quiero agregar a la respuesta ya aceptada. Estaba atrapado en esto, pero estaba yendo por una ruta diferente en el manejo del evento completo. En lugar de ejecutar aguardar, agrego un controlador completado a la tarea.
Donde el controlador de eventos se ve así
Con esta ruta, todo el manejo ya está hecho para usted, cuando la tarea se cancela, solo activa el controlador de eventos y puede ver si se canceló allí.
fuente