2012-09-24 12 views
7

Estoy intentando permitir la cancelación de un Parallel.ForEach loop. De acuerdo con this MSDN article, es posible, y estoy siguiendo su codificación.OperationCanceledException no controlada cuando se lanza desde Parallel.ForEach

// Tokens for cancellation 
ParallelOptions po = new ParallelOptions(); 
po.CancellationToken = cts.Token; 

try 
{ 
    Parallel.ForEach(queries, po, (currentQuery) => 
    { 
     // Execute query 
     ExecuteQuery(currentQuery); 

     // Throw exception if cancelled 
     po.CancellationToken.ThrowIfCancellationRequested(); // *** 
    }); 
} 
catch (OperationCanceledException cancelException) 
{ 
    Console.WriteLine(cancelException.Message); 
} 

Sin embargo, cuando llamo cts.Cancel(); de una función para el usuario, la aplicación se bloquea en la línea marcada con asteriscos anterior con el error:

System.OperationCanceledException was unhandled by user code 
    Message=The operation was canceled. 
    Source=mscorlib 
    StackTrace: 
    at System.Threading.CancellationToken.ThrowIfCancellationRequested() 
    at CraigslistReader.SearchObject.<>c__DisplayClass7.<bw_DoWork>b__5(Query currentQuery) in {PATH}:line 286 
    at System.Threading.Tasks.Parallel.<>c__DisplayClass2d`2.<ForEachWorker>b__23(Int32 i) 
    at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c() 
InnerException: 

tengo el gestor de excepciones allí mismo, por lo No entiendo el choque. ¿Algunas ideas?

+0

No veo el problema que está describiendo, el 'catch' funciona bien para mí. ¿Podría publicar un código completo pero breve que muestre su problema? – svick

+0

No creo que la aplicación se haya bloqueado, al menos no con esta excepción. O bien tu aplicación no se ha bloqueado (¿cómo sabes que se ha bloqueado?), O esta no es la última excepción que está ocurriendo. – usr

+0

@usr Sí, tenías razón. Lo estaba ejecutando en el depurador y cuando vi que la excepción detenía el tiempo de ejecución, pensé que era una excepción que bloquearía la aplicación. No sabía que algunas excepciones no se están rompiendo. – Doug

Respuesta

2

El problema es que po.CancellationToken.ThrowIfCancellationRequested(); está lanzando explícitamente una excepción, que no se ha manejado. El controlador de excepción puede estar alrededor de la llamada Parrallel.ForEach() pero la excepción no se maneja dentro de la expresión lambda. Elimine la línea o agregue un manejador de excepciones dentro de la expresión lambda y debería funcionar.

Consulte Cancelling a Task is throwing an exception para obtener más información.

+0

Entonces, ¿está diciendo que el ejemplo de MSDN es incorrecto? – svick

+0

@svick Posiblemente. Echa un vistazo a la respuesta que he vinculado y prueba lo que sugiere. Si funciona, funciona. – akton

+0

@akton: Intenté poner el try/catch dentro de la expresión lamba y todavía resulta en un error de tiempo de ejecución. – Doug

Cuestiones relacionadas