3

Given is a very common threading scenario:

Declaration

private Thread _thread; private bool _isRunning = false; 

Start

_thread = new Thread(() => NeverEndingProc()); thread.Start(); 

Method

private void NeverEndingProc() { while(_isRunning) { do(); } } 

Possibly used in a asynchronous tcp listener that awaits callbacks until it gets stopped by letting the thread run out (_isRunning = false).

Now I'm wondering: Is it possible to do the same thing with Task? Using a CancellationToken? Or are Tasks only for procedures that are expected to end and report status?

3
  • You just want to create an infinite loop with cancellation option using tasks? Commented Nov 12, 2013 at 13:40
  • @Deffiss Basically, yes. I was once told are 'just' threads, but on a higher level which behave slightly different, but serve the same purpose. I might be wrong on this, though. Commented Nov 12, 2013 at 13:44
  • I think that _isRunning needs to be volatile. Otherwise, the compiler might realize it's not modified from the current thread and check it only once before the loop starts. Commented Nov 12, 2013 at 14:06

2 Answers 2

3

You can certainly do this just by passing NeverEndingProc to Task.Run.

However, there is one important difference in functionality: if an exception is propagated out of NeverEndingProc in a bare Thread, it will crash the process. If it is in a Task, it will raise TaskScheduler.UnobservedException and then be silently ignored (as of .NET 4.5).

That said, there are alternatives you can explore. Reactive Extensions, for example, pretty much removes any need for the "infinite thread loop".

Sign up to request clarification or add additional context in comments.

10 Comments

TaskCreationOptions.LongRunning is necessary here isn't it? So Factory.StartNew with TaskCreationOptions and "DefaultScheduler" would be the preferable option than Task.Run. Correct me if am wrong
Reactive Extensions really sounds promising, but currently I don't have the time to dig into another new tool. :)
@SriramSakthivel: LongRunning is just a hint. Unless you're already doing really intensive parallel processing at the time you start the "infinite loop" task, it's unnecessary. And Task.Run uses the default scheduler.
@StephenCleary Am not sure what you mean by "it is unnecessary". Without that ThreadPool will use pool's thread right? enabling that makes dedicated thread for the task, allowing pool's threads to take care of other small cpu intensive operations?
@ErwinMayer: I believe so, but I'm not entirely sure.
|
1

One reason to use Task + CancellationToken is to make the individual processes and their cancellation more independent of each other. In your example, notice how NeverEndingProc needs a direct reference to the _isRunning field in the same class. Instead, you could accept an external token:

Start:

public void StartNeverEndingProc(CancellationToken token) { Task.Factory.StartNew(() => NeverEndingProc(token), token); } 

Method:

private void NeverEndingProc(CancellationToken token) { while (true) { token.ThrowIfCancellationRequested(); do(); } } 

Now cancellation is managed by the caller, and can be applied to multiple independent tasks:

var instance = new YourClass(); var cts = new CancellationTokenSource(); instance.StartNeverEndingProc(cts.Token); // start your task StartOtherProc(cts.Token); // start another task cts.Cancel(); // cancel both 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.