У меня есть задача, которая запускает несколько дочерних задач. (например, задача A создает B, C, D, E, F). Я также создаю System.Threading.Timer
для опроса базы данных каждые 10 секунд, чтобы проверить, был ли запланированный элемент отменен по запросу. Если это так, он устанавливает CancellationTokenSource
, чтобы задача могла отказаться. Каждая подзадача, в этом случае B, C, D, E, F, отменит, когда это необходимо (они перемещаются по файлам и перемещают их).
Так как Task
реализует IDisposable
, я хочу знать, стоит ли снова вызывать Task.WaitAll
из блока catch
, чтобы дожидаться аннулирования. Пока запрос на отмену будет обработан, подзадачи могут находиться в середине цикла и не могут отменить до тех пор, пока это не завершится
Однако для MSDN:
Всегда вызывайте Dispose перед тем, как вы отпустите свою последнюю ссылку на Задачу. В противном случае ресурсы, которые он использует, не будут освобождены до тех пор, пока сборщик мусора не вызовет метод Finalize объекта Task.
Должен ли я снова вызвать wait на моем массиве задач, чтобы правильно вызвать Dispose()
для каждой задачи в массиве?
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.
}
}
}