Does Task.Wait(int) stop the task if the timeout elapses without the task finishing?
Solution 1
If you want to cancel a Task
, you should pass in a CancellationToken
when you create the task. That will allow you to cancel the Task
from the outside. You could tie cancellation to a timer if you want.
To create a Task with a Cancellation token see this example:
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var t = Task.Factory.StartNew(() => {
// do some work
if (token.IsCancellationRequested) {
// Clean up as needed here ....
}
token.ThrowIfCancellationRequested();
}, token);
To cancel the Task
call Cancel()
on the tokenSource
.
Solution 2
Task.Wait()
waits up to specified period for task completion and returns whether the task completed in the specified amount of time (or earlier) or not. The task itself is not modified and does not rely on waiting.
Read nice series: Parallelism in .NET, Parallelism in .NET – Part 10, Cancellation in PLINQ and the Parallel class by Reed Copsey
And: .NET 4 Cancellation Framework / Parallel Programming: Task Cancellation
Check following code:
var cts = new CancellationTokenSource();
var newTask = Task.Factory.StartNew(state =>
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
}
token.ThrowIfCancellationRequested();
}, cts.Token, cts.Token);
if (!newTask.Wait(3000, cts.Token)) cts.Cancel();
Solution 3
The task is still running until you explicitly tell it to stop or your loop finishes (which will never happen).
You can check the return value of Wait to see this:
(from http://msdn.microsoft.com/en-us/library/dd235606.aspx) Return Value
Type: System.Boolean true if the Task completed execution within the allotted time; otherwise, false.
Solution 4
Was the task canceled when the timeout expired or is the task still running?
No and Yes.
The timeout passed to Task.Wait
is for the Wait
, not the task.
Paul Mendoza
Paul Mendoza has been developing software and web solutions for companies in Southern California. Paul is an expert in developing and architecting .NET solutions including the development of multiple online social networking applications, data analytics tools and working with customers to provide value driven results. Paul has given talks at conferences on topics ranging from SQL Server spatial data to how to write maintainable JavaScript.
Updated on July 22, 2022Comments
-
Paul Mendoza over 1 year
I have a task and I expect it to take under a second to run but if it takes longer than a few seconds I want to cancel the task.
For example:
Task t = new Task(() => { while (true) { Thread.Sleep(500); } }); t.Start(); t.Wait(3000);
Notice that after 3000 milliseconds the wait expires. Was the task canceled when the timeout expired or is the task still running?
-
BitMask777 over 9 yearsDoesn't this allow you to only request cancellation "from the outside"? Wouldn't it be up to the delegate whether it pays attention to the token-based request and actually throws or just continues working without cancellation?
-
Brian Rasmussen over 9 yearsCorrect, the delegate decides whether it will act on the request by checking the
IsCancellationRequest
on the property. -
Michael R almost 9 yearsThis is interesting, because the help text here seems to say the opposite: msdn.microsoft.com/en-us/library/dd270644(v=vs.110).aspx says, "Waits for the Task to complete execution within a specified number of milliseconds." Not sure if I understand this yet.
-
Michael R almost 9 yearsI noticed that the
cts.Token
is also passed to theWait()
method. I found a note in Microsoft's documentation: "Passing the cancellationToken object to this method simply allows the wait to be canceled based on some condition." msdn.microsoft.com/en-us/library/dd321457%28v=vs.110%29.aspx -
Richard almost 9 years@Michael If the time passed to
Wait
expires it will return, even if the task has not completed. In this timeout case the task will continue to execute until it completes (and a laterWait
would thus return as completed). -
bside over 5 yearsLast row can look prettier, like this:
cts.CancelAfter(3000); newTask.Wait(cts.Token);