2013-07-18 3 views
0

У меня есть class WorkerTaskEvent : IDisposable, который имеет свойство типа Task. При создании он создаст новую задачу, которая будет запускать какой-то метод в фоновом режиме, который должен заканчиваться в какой-то момент.
Однако иногда задача не заканчивается, тем самым сохраняя вещи в памяти навсегда. Сейчас я использую маркер отмены, чтобы отправить сообщение об отмене и я делаю это так:Устранение объекта с запущенной задачей?

public WorkerTaskEvent(ExecuteTaskMethod taskMethod) 
{ 
    TaskMethod = taskMethod; 
    RunningTask = Task.Factory.StartNew(OnExecuteTask, Token.Token); 
} 

private void OnExecuteTask() 
{ 
    if (TaskMethod != null) TaskMethod(); 
} 

public void Dispose() 
{ 
    if (RunningTask != null && !RunningTask.IsCompleted) 
    { 
     Token.CancelAfter(TimeSpan.FromMinutes(1)); 
    } 
} 

(. Там больше кода, включая код, чтобы проверить, если задача завершается в течение определенного периода времени)
I не может выполнить эту задачу навсегда, и я надеюсь, что это правильное решение, но, возможно, у кого-то есть лучший вариант?
У меня нет абсолютно никакого контроля над тем, что TaskMethod будет делать точно, поэтому, если любые ресурсы будут потеряны, когда этот метод будет убит, штраф. Тем не менее, он не идеален. Но очистка будет зависеть от тех, кто создает метод, стоящий за этим делегатом.

Передача маркера отмены на делегированный метод может помочь много, я не могу использовать это как решение, поскольку делегированный метод является частью сторонней библиотеки, и он не должен заканчиваться бесконечным циклом. Закон Мерфи снова смеется мне в лицо, потому что делегат, как правило, бесконечно зацикливается. Может быть, я могу передать токен отмены в следующей версии этой библиотеки (я просил об этом), но на данный момент мне приходится останавливать бесконечный цикл в трудной ситуации ...

+0

No. Мне нужно знать, если я могу закончить нить в некотором роде, если она заканчивается в бесконечном цикле. Но я нашел альтернативное решение, поэтому Q может оставаться закрытым. –

ответ

1

Отмена задачи является совместной и должна не быть вынужденным.

Когда вы передаете токен отмены до Task.Factory.StartNew(), это относится к случаю, когда источник токена отменяется еще до того, как задача была запланирована. Однако, как только задача запустилась, ответственность за выполнение делегата - проверка и остановка отмененного токена.

Следовательно, вы должны определить своего делегата ExecuteTaskMethod так, чтобы он принял параметр CancellationToken. Затем вы оставите это для выполнения делегата для отмены на токене.

private void OnExecuteTask() 
{ 
    if (TaskMethod != null) TaskMethod(Token.Token); 
} 

Смотрите также ответ здесь: How do I abort/cancel TPL Tasks?

+0

К сожалению, токен отмены не может быть передан делегированному методу, так как это код вне моего контроля и часть пользовательской библиотеки. Предполагается, что в этой пользовательской библиотеке не будет бесконечных циклов, но иногда она заканчивается бесконечным циклом без возможности ее прекратить. (И никоим образом не изменить код.) –

+0

Один из альтернатив - создать экземпляр 'WorkerTaskEvent' в новом AppDomain, а затем свернуть AppDomain, когда вы хотите заставить убить эту задачу, - это предполагает, что вы сказали« так, если любые ресурсы потеряны когда этот метод убит, штраф'. – YK1

Смежные вопросы