2

I have a data extraction task, which is refreshing the UI, and once the refresh is done, it is tasking another such call in a task.

private void startTheDataExtraction()
{
    Task<JObject> task = Task<JObject>.Factory.StartNew(() =>
    {
        JObject r = new JObject();
        
        r = DataExtractor.getControllersData();

        return r;
        
    });            

    Task UITask = task.ContinueWith( ( ret ) =>
    {
        //set the UI controls data

        // reshedule next interaction
        resheduleDataExtraction();
    }, 
    TaskScheduler.FromCurrentSynchronizationContext() );
}

public void resheduleDataExtraction()
{
    Task.Delay( 1000 ).ContinueWith( _ =>
    {
        startTheDataExtraction();
    } );

}
  • I wonder if at some point this recursive task calling will consume some sort of resources and prevent further the execution in some way ?
ASh
  • 34,632
  • 9
  • 60
  • 82
Yordan Yanakiev
  • 2,546
  • 3
  • 39
  • 88
  • Why are you using `Task.Factory` instead of `Task.Run` - or just `async`? – Dai Apr 21 '23 at 09:37
  • First off, use `async/await` rather than `ContinueWith` -- it avoids a lot of nasty edge cases. But this is safe. – canton7 Apr 21 '23 at 09:37
  • 5
    `resheduleDataExtraction` <-- Consider having a `while( true ) { await Task.Delay( 1000 ); await DoStuffAsync();` instead of mutual-invocation (which is harder to follow) – Dai Apr 21 '23 at 09:38
  • 4
    Or just use a `PeriodicTimer` – canton7 Apr 21 '23 at 09:39
  • I also think the better alternative is [PeriodicTimer](https://learn.microsoft.com/en-us/dotnet/api/system.threading.periodictimer?view=net-6.0), but someone should address **the actual question** _"I wonder if at some point this recursive task calling will consume some sort of resources and prevent further the execution in some way ?"_ - Of which I am myself also not 100% sure. – Fildor Apr 21 '23 at 09:46
  • 2
    @Fildor Pretty sure this is "safe" in terms of resources and stack overflow, but it's horribly unreadable and confusing. – DavidG Apr 21 '23 at 09:47
  • 2
    Yeah it's safe, see the end of my first comment. It's the same as task 1 putting task 2 onto a queue, and task 2 putting task 1 onto the same queue, while a separate thing processes and executes tasks from the queue. – canton7 Apr 21 '23 at 09:49
  • 1
    @DavidG Yes, I am "pretty sure", too. But I couldn't back that claim with hard facts, I have to admit. The only explanation I'd have is that this seemingly "recursive" call is in fact not at all really recursive, as canton7 explained. But I lack the deeper knowledge to point to code or documentation to confidently post an answer. – Fildor Apr 21 '23 at 09:49
  • 1
    I don't see any error-handling code here - so **yes**, this could simply fall-apart as soon as an exception is thrown. – Dai Apr 21 '23 at 09:58
  • I believe that I've stumbled upon issue with this code now, and not sure the cause. DataExtractor.getControllersData(); calling is actually a calling to WebRequest, and if there is no server - the whole application, and even the desktop go frozen. – Yordan Yanakiev May 01 '23 at 11:17

1 Answers1

3

Your example does not do actual recursion, so you are safe from stack overflows. You are just asking the threadpool to run some code from a thread pool thread, and that is perfectly safe an normal. That you are asking it to run the same code you are currently running is irrelevant.

That said, this is not the way to run things periodically. Use one of the timer classes instead, or the somewhat newer PeriodicTimer. That should result in code that is much easier to read and understand.

JonasH
  • 28,608
  • 2
  • 10
  • 23