2

Thread supports interrupt. Why doesn't Task?

From my (uninformed) perspective, it seems reasonable to allow Task to support interruption:

  • If the Task isn't currently being executed on a Thread, calling task.Interrupt() will set a TaskInterruptException to be thrown when the Task is scheduled.
  • Otherwise, the TaskInterrupException will be thrown in the thread executing the task, which exception will either be caught within the task or added to the AggregateException at the top. I guess this feature would require the task to know the executing thread (is this unreasonable?)

Do the pieces needed to implement this feature already exist, or would this require changes to the language implementation?

Addition: I have read numerous questions on SO that discuss killing/aborting Tasks, with their associated answers discussing CancellationToken and the (discouraged) Thread.Abort approach.

In my own fiddling, I discovered that registering Thread.Interrupt with CancellationToken.Register doesn't interrupt the thread running in the task, but instead interrupts the thread calling cancel on the token.

So, as I see it, there is still a need for a sanctioned feature allowing the developer to ensure a Task can be (gently) terminated.

I will also add (lest someone say "re-write your Tasks to take CancellationTokens") that this feature is particularly valuable in situations where the developer does not own the code being executed in the Tasks.

And, on matter of principle, it seems that there should be a way for the executor of the Task to be able to provide a guarantee of cancellation, rather than depending on the implementer of the Task to do things correctly with a cancellation token.

Another addition: Regardless of the risks, the C# API supports Thread.Abort and Thread.Interrupt. So my question is, essentially, why doesn't Task support the same API (with the same inherent risks)?

Update
This post has been marked as a duplicate of this question. However, I had already read the referenced question before posting this one (and all of the answers) - this question is not a duplicate, but a related question seeking additional information. That question asks "can you abort" and the answers are essentially "you should not abort" - my question asks "Given that interrupt is better than abort, why isn't interrupt a supported feature? What mechanical hurdles prohibit this feature?". According to this question, there are important differences between interrupting and aborting a thread, and that interrupt is much preferred.

Community
  • 1
  • 1
Gordon Bean
  • 4,272
  • 1
  • 32
  • 47
  • 3
    http://stackoverflow.com/a/14831590/17034 – Hans Passant Oct 07 '16 at 23:15
  • Thank you for the link, Hans. There you discuss Thread.Abort. Is the same true for Thread.Interrupt? I understood that Thread.Interrupt was supposed to avoid throwing exceptions in nasty locations. – Gordon Bean Oct 07 '16 at 23:25
  • Also, regardless of the risks, the API still supports Thread.Abort and Thread.Interrupt. My question is why doesn't Task support the same? – Gordon Bean Oct 07 '16 at 23:32
  • 1
    If you have third-party code that you feel you need to abort then you really must run that code in a separate App Domain or Process. That's the only way to cleanly abort. Otherwise you should use the co-operative cancellation model. – Enigmativity Oct 08 '16 at 04:21

1 Answers1

1

And, on matter of principle, it seems that there should be a way for the executor of the Task to be able to provide a guarantee of cancellation, rather than depending on the implementer of the Task to do things correctly with a cancellation token.

I would disagree with that statement. Any hard about have a high risk of leaving your system in undetermined state, where it cannot just continue functioning normally, especially if you are trying to abort Tasks which code you don't own.

So designed graceful cancellation of a Task is the only way to avoid such situations. Would you prefer a system in production (that is designed to run 24/7) to leaks resources and crash unexpectedly, or just waste some extra resources and time when you don't have an ability to cancel a Task that does not take in a CacnellationToken?

This is my personal opinion, and I find a Task.Abort() rather harmful than useful in most cases.

EDIT: Besides, a Task is just a handle to an operation, you can create a TaskCompletionSource<T> and set the completion at any point of time on any thread, so it's not possible to track down the thread(s) where logical code behind that Task is actual running. For instance, the Task.WhenAll(Task[]) returns a Task. How would you abort that? It's not running on any thread, but instead listens on completion of given tasks. I.e. it's just not technically feasible to add a general Abort method.

Serge Semenov
  • 9,232
  • 3
  • 23
  • 24
  • Serge, I'm glad you added the edit - that is the kind of information I was looking for in this question. To restate: "the actual code supporting a Task and the Task handle might not be connected, making it impossible to identify via the Task the code needing to be interrupted." – Gordon Bean Oct 10 '16 at 16:02
  • I understand that code intended for 24/7 running would never want to abort a thread. However, my use-case is computational pipelines running on a pay-per-hour basis. If something goes wrong, we want to bring down everything as quickly as possible (so the user doesn't get charged extra), while also cataloging the sources of error as accurately as possible (so we can fix the problem in our pipeline). – Gordon Bean Oct 10 '16 at 16:21
  • It still should be technically possible to forcibly abort a `Task` using some wrappers, `Thread.Abort()`, and `Thread.ResetAbort()`. You can add another question on SO on how exactly to do that - because this is the only cheapest way to solve a problem in your particular case. – Serge Semenov Oct 11 '16 at 21:50