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