Как насчет чего-то вроде следующего. Я уверен, что API можно немного почистить.
Очки на заметку:
Метод DoWork должен поддерживать совместную отмену, это единственный подход отмены, поддерживаемый библиотекой параллельных задач.
Таймер должен запускаться внутри Задачи, иначе Задача может быть создана и запланирована, но не выполнена, и таймер будет временем ожидания задачи, а не временем выполнения.
Если вы хотите предоставить другие внешние механизмы для отмены (другие токены), тогда вам нужно перейти в другой контекст и связать их. См .: CancellationTokenSource.CreateLinkedTokenSource
Это только приблизительно, как System.Threading.Timer только с точностью до миллисекунды. Это должно быть достаточно, чтобы ограничить выполнение задачи на несколько секунд.
public static class TimeLimitedTaskFactory
{
public static Task StartNew<T>
(Action<CancellationToken> action, int maxTime)
{
Task tsk = Task.Factory.StartNew(() =>
{
var cts = new CancellationTokenSource();
System.Threading.Timer timer = new System.Threading.Timer(o =>
{
cts.Cancel();
Console.WriteLine("Cancelled!");
}, null, maxTime, int.MaxValue);
action(cts.Token);
});
return tsk;
}
}
class Program
{
static void Main(string[] args)
{
int maxTime = 2000;
int maxWork = 10;
Task tsk = TimeLimitedTaskFactory
.StartNew<int>((ctx) => DoWork(ctx, maxWork), maxTime);
Console.WriteLine("Waiting on Task...");
tsk.Wait();
Console.WriteLine("Finished...");
Console.ReadKey();
}
static void DoWork(CancellationToken ctx, int workSize)
{
int i = 0;
while (!ctx.IsCancellationRequested && i < workSize)
{
Thread.Sleep(500);
Console.WriteLine(" Working on ", ++i);
}
}
}