Я хотел бы начать пользоваться Библиотекой Параллели Задачи, поскольку это - рекомендуемая платформа, продвигающаяся для выполнения асинхронных операций. Одной вещью, которую я не смог найти, являются любые средства насильственного Аварийного прекращения работы, такой как какой Поток. Аварийное прекращение работы обеспечивает.
Мое особое беспокойство - то, что я планирую задачи, выполняющие код, которого я не желаю к абсолютно доверительному. В частности, я не могу быть уверен, что этот недоверяемый код не зайдет в тупик, и поэтому я не могу быть уверен, будет ли Задача, я планирую использование этого кода, когда-либо завершаться. Я хочу избегать истинной изоляции AppDomain (из-за издержек и сложности маршалинга), но я также не хочу оставлять поток Задачи бродящим вокруг, заведенным в тупик. Существует ли способ сделать это в TPL?
Это можно сделать с помощью CancellationToken и новой модели отмены. Новая модель отмены интегрирована в .NET Framework в нескольких типах. Наиболее важными из них являются System.Threading.Tasks, System.Threading.Tasks.Task, System.Threading.Tasks.Task и System.Linq.ParallelEnumerable.
Вот пример вашей проблемы. Этот код всегда будет блокироваться, потому что вызывающий код сначала принимает блокировку, а затем заблокированная задача пытается получить ту же блокировку.
public void Example()
{
object sync = new Object();
lock (sync)
{
CancellationTokenSource canceller = new CancellationTokenSource();
ManualResetEvent started = new ManualResetEvent(false);
Task deadlocked = Task.Factory.StartNew(() =>
{
started.Set();
// EVIL CODE: This will ALWAYS deadlock
lock(sync) { };
},
canceller.Token);
// Make sure task has started.
started.WaitOne();
canceller.Cancel();
try
{
// Wait for task to cancel.
deadlocked.Wait();
}
catch (AggregateException ex)
{
// Ignore canceled exception. SIMPLIFIED!
if (!(ex.InnerException is TaskCanceledException))
throw;
}
}
}
Отмена задачи в TPL является кооперативной. Другими словами, это всегда будет взаимоблокировкой, потому что ничто не обрабатывает токен отмены, установленный на отмену, потому что поток задачи заблокирован.
Есть способ обойти это, но он по-прежнему полагается на то, что авторы ненадежного кода поступят правильно:
public static void Example2()
{
Mutex sync = new Mutex(true);
CancellationTokenSource canceller = new CancellationTokenSource();
bool started = false;
Task deadlocked = Task.Factory.StartNew(() =>
{
started = true;
// EVIL CODE: This will ALWAYS deadlock
WaitHandle.WaitAny(new WaitHandle[] { canceller.Token.WaitHandle, sync });
},
canceller.Token);
// Make sure task has started.
while (!started) { }
canceller.Cancel();
try
{
// Wait for task to cancel.
deadlocked.Wait();
}
catch (AggregateException ex)
{
// Ignore canceled exception. SIMPLIFIED!
if (!(ex.InnerException is TaskCanceledException))
throw;
}
}
На заметку; отмена возможна. Вы можете использовать Token.WaitHandle, чтобы получить дескриптор и ждать его вместе с дескриптором (ами) других примитивов синхронизации. Mutex намного медленнее, чем Monitor (или lock).
На самом деле, если вы недостаточно доверяете автору кода, чтобы он реализовал совместную отмену, я бы поставил под сомнение разумность их запуска внутри вашего AppDomain в одном потоке.
Подробнее см .:
http://msdn.microsoft.com/en-us/library/dd997364.aspx
Вы просто вызываете Task.Wait (timespanToWait)
.
Если задача не завершена по истечении указанного промежутка времени, она отменяется.
Dan Я не думаю, что Task.Wait(timeout) отменит эту задачу, есть перегрузка Task.Wait(timeout,cancelationToken), но это только бросает OperationCanceledException на task.Wait, когда токен сигнализируется.
Task.Wait блокирует только до тех пор, пока либо задача не завершится, либо не истечет таймаут, он не отменяет и не прерывает задачу. Поэтому зашедшая в тупик задача останется висеть в ThreadPool. Вы не можете утилизировать незавершенную задачу (InvalidOperation).
Я пишу такое же приложение, как и вы, и я написал свой собственный TaskScheduler, который позволяет прервать выполнение (и не использует threadpool :( ).
Но мне очень интересно, как вы решили эту проблему. Пожалуйста, ответьте мне.