1

I am trying to run a task in the background checking a database for a number of records in a table, and if the number has changed since the last check, get those records, and do some work on them.

Using the following code, I'm getting a stack overflow after about two hours. The application is doing nothing during this time, just checking, and no jobs are being added to the database.

private Thread threadTask = null;
private int recordCount = 0;

private void threadTask_Start()
{
    if (threadTask == null) {
        threadTask = new Thread(taskCheck);
        threadTask.Start();
    }
}

private void taskCheck()
{
     int recordCountNew = GetDBRecordCound();
     if (recordCountNew != recordCount)
     {
         taskDo();
         recordCount = recordCountNew; // Reset the local count for the next loop
     }
     else
         Thread.Sleep(1000); // Give the thread a quick break

     taskCheck();          
}

private void taskDo()
{
    // get the top DB record and handle it
    // delete this record from the db
}

When it overflows, there are a ton of taskCheck() in the call stack. I'm guessing that taskCheck() never completes until taskCheck() completes, ergo overflow, and hence why they all remain in the stack. This is obviously not the right way to go about this, so what is?

2
  • Aren't you calling taskCheck() at the bottom of taskCheck()? The underscore is a typo, right? Commented May 5, 2009 at 21:50
  • I think I see where you're coming from. No - C#/.NET doesn't apply TCO - you have to do the looping manually. Commented May 5, 2009 at 22:47

2 Answers 2

9

You get a stack overflow because at the end of taskCheck, you call taskCheck again. You never exit the function taskCheck, you just end up calling more and more until your stack overflows. What you should do is have a while loop in taskCheck instead:

private void taskCheck()
{
   while(true)
   {
       int recordCountNew = GetDBRecordCound();
       if (recordCountNew != recordCount)
       {
           taskDo();
           recordCount = recordCountNew; // Reset the local count for the next loop
       }
       else
           Thread.Sleep(1000); // Give the thread a quick break
   }
}
Sign up to request clarification or add additional context in comments.

3 Comments

He should also have a try{}catch(ThreadAbortException){}finally{} block.
good point. If an exception is thrown (database call?) the flow of execution will exit the while loop and the while loop will stop executing. I usually inform the user in a message log or pop up if this occurs. Alternatives?
There is other database handling going on, which I'll use to control the 'true' value if there is a problem.
1

I'm assuming where you have task_Check(), you actually mean taskCheck() (or vice-versa). That is, you're calling the taskCheck() method recursively. Avoiding the discussion of the architecture here, you could remove that call and have threadTask_Start() repeat the process once in a while loop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.