Background
I have a Service
abstraction. Each service has it own WorkItem
. WorkItem able to start with some data. The service is limiting the excution time of WorkItem
. Let's say that a single workitem can takes up to 60 seconds. After this, the Service
should kill it.
This code migrated from the .NET Framework, I created a Thread
object which run the Start(model)
method. Then the code was something like:
Thread t = new Thread(workItem.Start, model);
t.start();
if (!t.Join(TimeSpan.FromSeconds(60)))
t.Abort();
The Thread.Abort
was injecting an exception for the running thread, which lead it for immediately stop.
Now, I moved the code to dotnet core - as you may know, when you calling Thread.Abort()
your getting the following message:
System.PlatformNotSupportedException: Thread abort is not supported on this platform.
at System.Threading.Thread.Abort()
at ...
The Goal
I want to limit the execution time of the WorkItem
to specific amount of time. Note that this limitation should work also if you running code line like this:
Thread.Sleep(61000); // 61 seconds. should be stop after 60 seconds.
Progress
On the dotnet core world, it's seems like it's going to the Task
related solution. So, I thought to use CancellationToken
. But its seems like its impossible to watch the "Canceled" event and stop immediately. The examples I saw are using while (!canceled)
loops, which cant stop long operations (like Thread.Sleep(1000000)
.
Question
How to do it right?
Update
I written this sample code:
public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
if (!task.Wait(timeSpan))
{
// ABORT HERE!
Console.WriteLine("Time exceeded. Aborted!");
}
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
And this Main
file:
public static void Main(string[] args)
{
bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(2000), () =>
{
Console.WriteLine("start");
Thread.Sleep(3000);
Console.WriteLine("end");
});
Console.WriteLine($"Completed={Completed}");
Console.ReadLine();
}
Expected: "end" wont be printed to the screen. Actual: "end" printed. Is there any alternative that can kill a Task
?
Thread.Sleep
– SmallmindedThread.Sleep
is just example. I can think of other examples which not supporting the async model. Another example: downloading a file withWebClient
and the server is really slow, therefore it takes too much time (exceed the limit). – DummyThread.Abort
is to create a seperated process for eachWorkItem
and kill it if running to much time - sounds to me too much resources will be consumed. – DummyisStopping
if I could. so what do you do with threads that are waiting on a blocking operation? – Martinson