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
CancellationTokencon losasyncmétodos.Para resumir, pasa un
CancellationTokenmétodo a cada método que admite la cancelación, y ese método debe verificarlo periódicamente.fuente
CancellationTokentiene todos los ganchos necesarios para interoperar con sistemas de cancelación personalizados, pero nada puede cancelar un método no cancelable.WaitoResultenasyncmétodos; siempre debe usarloawait, lo que desenvuelve la excepción correctamente.CancellationToken.IsCancellationRequestedy 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
ConfigureAwaitcontrario, 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
CancelAsyncllamada en el ejemplo, o mejor aún, pasar el mismoCancellationTokenalTaskpara que pueda manejar la cancelación eventualmente. Intentar abortar el hilo no es recomendable .fuente
UploadDataAsyncpuede continuar en segundo plano, pero una vez que se complete, no realizará la llamadaCalculateAsyncporque esa parte ya dejó de esperar). Esto puede o no ser problemático para usted, especialmente si desea volver a intentar la operación. PasarCancellationTokentodo 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