ThreadPool with 2 WaitCallback will sometimes be stuck

651 Views Asked by At

I'm trying to work with ThreadPool.QueueUserWorkItem but it seems that if i'll run 2 of them, meaning:

ThreadPool.QueueUserWorkItem(new WaitCallback(x=>function A); 
ThreadPool.QueueUserWorkItem(new WaitCallback(x=>function B);

It sometimes will be stuck for less than a second. Any ideas?

one of the calls is a game countdown timer:

ThreadPool.QueueUserWorkItem(new WaitCallback(x=>initClock(0,0)));

private void initClock(int sec , int hunS)
{
    int half = gameClock / 2;
    seconds = sec;
    while (true)
    {   
        while (clockLock == false && seconds < gameClock)
        {
            hunSec = hunS;
            while (clockLock == false && hunSec < 100)
            {
                Thread.Sleep(10);
                updateClock(seconds, hunSec);
                hunSec++;
            }
            seconds++;
            if (half == seconds)
            {
                panel5.BackColor = Color.Red;
            }
        } 
    }
}

private void updateClock(int sec, int secRem)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action<int, int>(updateClock), sec, secRem);
    }
    else
    {                
        clock_Label.Text = sec.ToString() + ':' + secRem.ToString();
    }
}
2

There are 2 best solutions below

0
On

There's something fishy in there. When does initClock ends? Looks like never, or more like it when you exit the application.

So, if you're starting many thread pool threads with the entry point initClock then that's why you run out of thread pool capacity. In this case it doesn't matter how much you increase the min threads, it will still behave like this.

I don't know the logic behind it, but I assume you want it to end when the remaining number of seconds is 0. So, of you correct this probably the behavior is fixed.

One last thing; this statement updates the UI:

        if (half == seconds)
        {
            panel5.BackColor = Color.Red;
        }

You should really dispatch its execution to the UI thread (via Invoke, like you did for updateClock). I know it may work, but that doesn't make it correct.

It sometimes will be stuck for less than a second. Any ideas? You must be referring to what you observe in the UI, that label clock_Label does not update as fast as you expect.

Well, for one I would decrease the refresh rate of that label. When you do update it you do so every 10ms. Is that necessary? Since you're displaying seconds in this label you might as well increase the interval to 500ms. See what differences it makes in responsiveness.

4
On

Are you starting many of those tasks, each of which block for a long time? According to the information given this might be the case.

This means that a lot of threads can be active at at a time. When you use the thread-pool above the minimum limits starting an additional thread will be throttled for (I believe) 500ms. This might be the delay you are seeing.

How to resolve that problem?

  1. Start less threads. Use async IO and async waiting. Those do not use any threads. With await it is quite easy to do that.
  2. Increase the thread pool minimum limits. SetMinThreads.