Tengo una tarea que inicia varias tareas secundarias. (Por ejemplo, la Tarea A crea B, C, D, E, F). También creo un System.Threading.Timer
para sondear una base de datos cada 10 segundos para verificar si el elemento programado fue cancelado por solicitud. Si lo hace, establece CancellationTokenSource
para que la tarea sepa cancelar. Cada subtarea, en este caso B, C, D, E, F, se cancelará cuando corresponda (están haciendo un bucle a través de archivos y moviéndolos).¿Cuándo deshacerse de System.Threading.Task con tareas secundarias?
Desde Task
implementos IDisposable
, quiero saber si es una buena idea llamar a Task.WaitAll
de nuevo desde el bloque catch
, que esperar a que las cancelaciones a propagar. Mientras se procesa la solicitud de cancelación, las sub-tareas pueden estar en el medio de un bucle y no se pueden cancelar hasta que completa
Sin embargo, por MSDN:
llamar siempre a botar antes de soltar su última referencia a la Tarea. De lo contrario, los recursos que está utilizando no se liberarán hasta que el recolector de elementos no utilizados llame al método Finalizar del objeto Tarea.
¿Debo llamar a esperar de nuevo en mi serie de tareas con el fin de llamar adecuadamente Dispose()
en cada tarea en la matriz?
public class MyCancelObject
{
CancellationTokenSource Source { get;set;}
int DatabaseId { get;set;}
}
private void CheckTaskCancelled(object state)
{
MyCancelObject sourceToken = (MyCancelObject)state;
if (!sourceToken.CancelToken.IsCancellationRequested)
{
//Check database to see if cancelled -- if so, set to cancelled
sourceToken.CancelToken.Cancel();
}
}
private void SomeFunc()
{
Task.StartNew(() =>
{
MyCancelObject myCancelObject = new MyCancelObject(
databaseId,
new CancellationTokenSource());
System.Threading.Timer cancelTimer = new Timer(
new TimerCallback(CheckIfTaskCancelled),
myCancelObject,
10000,
10000);
Task[] someTasks = new Task[someNumberOfTasks];
for (int i = 0; i < someNumberOfTasks; i++)
someTasks[i] = Task.Factory.StartNew(
() =>
{
DoSomeWork(someObject, myCancelObject.CancelToken.Token);
},
TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning,
myCancelObject.CancelToken.Token);
try
{
Task.WaitAll(someTasks, cts);
}
catch (AggregateException)
{
//Do stuff to handle
}
catch (OperationCanceledException)
{
//Should I call Task.WaitAll(someTasks) again??
//I want to be able to dispose.
}
}
}
Probé un código y encontré que 'Task.WaitAll' se puede llamar de nuevo para esperar de forma segura las tareas que aún se pueden estar ejecutando. Después de eso, pueden ser eliminados. Sin embargo, me gustaría saber si hay otras formas de manejar esto. –
No solo es aceptable para su propia pregunta, sino que se recomienda. Siéntete libre de publicar una respuesta y aceptarla si sientes que la has descubierto. –