2

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();
    }
}
Avi Levin
  • 1,868
  • 23
  • 32
  • Are starting many of those tasks, each of which block for a long time? Thread pool exhaustion. – usr Aug 03 '14 at 21:03
  • You should include more detail about those functions (what you really doo in those threads, if you e.g. lock something) – firda Aug 03 '14 at 21:06
  • Yes, I runing just 2 of threads one of them is for a very long time. – Avi Levin Aug 03 '14 at 21:07
  • Firda, I added more details. – Avi Levin Aug 03 '14 at 21:14
  • "a game countdown timer"... So **use a [timer](http://msdn.microsoft.com/en-us/library/system.threading.timer%28v=vs.110%29.aspx)** or use `async/await` and await a [`Task.Delay`](http://msdn.microsoft.com/en-us/library/hh194873%28v=vs.110%29.aspx) instead of blocking with `Thread.Sleep` in a tight, blocking loop. Blocking code has no place running in a threadpool, which is designed to run short, lightweight jobs that complete immediately. – spender Aug 03 '14 at 21:27
  • you need to add more details please,for example the second method and in what context do you call them,also how do you provide access to gameClock for example. – terrybozzio Aug 03 '14 at 21:47

2 Answers2

1

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.
usr
  • 168,620
  • 35
  • 240
  • 369
  • +1 for suggestion 1... -1 for suggestion 2! IMO if you are fiddling with the thread count of the threadpool, there's something that needs fixing. – spender Aug 03 '14 at 21:30
  • @spender... Where's your +1 :)? usr, at #1 you mean async waiting is not using thread pool threads, right? – Marcel N. Aug 03 '14 at 21:31
  • 1
    @spender it is a quick fix that works. Not doing that is preferable but with legacy code this can be a viable solution. I once increased limits to 500 threads for a legacy production app that was in trouble. Works fine and saved us code rewrites. Don't fear the thread :) If you disagree, try to formulate exactly why this is a bad idea. You won't be able to make a convincing argument. – usr Aug 03 '14 at 21:34
  • @MarcelN. it is not using *any* threads at all while the wait is running. – usr Aug 03 '14 at 21:34
0

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.

Marcel N.
  • 13,726
  • 5
  • 47
  • 72