Estoy ejecutando un hilo que tiene un

while(isRunning) 
{ 
    blockingCollection.Take()
}

Primero establezco isRunning en falso. Luego llamo a thread.Interrupt, lo que evita que blockingCollection espere nuevos elementos. Después de eso, llamo a mi método Dispose para la clase que ejecuta el Thread dentro del bloque catch.

¿Es esa la forma mejor / correcta de hacer esto?

4
Thypari 15 nov. 2017 a las 17:27

2 respuestas

La mejor respuesta

Un BlockingCollection tiene un método CompleteAdding () y es totalmente compatible con la cancelación.

while(isRunning && ! blockingCollection.IsCompleted) 
{ 
   isRunning = blockingCollection.TryTake(out someThing, -1, cancelToken);
}

De esta manera puede y debe dejar que el hilo termine normalmente, siempre la mejor opción.

6
Henk Holterman 15 nov. 2017 a las 15:35

Además de la respuesta de Henk, si prefiere tener la capacidad de bloqueo de Take () pero necesita cancelar mientras espera en una lista vacía, puede manejar la cancelación fuera del ciclo de esta manera.

private void DoSomething(CancellationToken token)
{
    while (IsRunning)
    {
        MyObject next;
        try
        {
            next = _queue.Take(token);
        }
        catch(OperationCanceledException)
        {
            break; //Cancelled
        }

        // Do something with 'next'
    }

    // Cleanup

}

Luego, cuando 'lo que sea' suceda que requiera que elimine este bucle, incluso si la lista está vacía y está bloqueado en la llamada Take (), simplemente llame a Cancel () en su CancellationTokenSource que generó el Token.

Nota - Por seguridad, probablemente también se recomienda capturar una ObjectDisposedException que Take () también puede lanzar. Consulte la documentación para obtener detalles sobre eso y por qué podría arrojar.

-1
Iain Stanford 14 abr. 2020 a las 07:18