1

Have created a class which implements ThreadPool. The code is as below:

public sealed class PyeThreadPool :

  IDisposable
{
    private readonly object _lock = new object();
    private readonly int _minThreadCount;
    private readonly int _maxThreadCount;
    private readonly Queue<Action> _queue = new Queue<Action>();
    private int _totalThreadCount;
    private int _waitingThreadCount;
    private bool _disposed;

    public PyeThreadPool(int minThreadCount, int maxThreadCount)
    {
        if (minThreadCount < 0)
            throw new ArgumentOutOfRangeException("minThreadCount");

        if (maxThreadCount < 1 || maxThreadCount < minThreadCount)
            throw new ArgumentOutOfRangeException("maxThreadCount");

        _minThreadCount = minThreadCount;
        _maxThreadCount = maxThreadCount;


    }
    public void Dispose()
    {
        lock (_lock)
        {
            _disposed = true;

            // if there are thread waiting, they should stop waiting.
            if (_waitingThreadCount > 0)
                Monitor.PulseAll(_lock);
        }
    }

    /// <summary>
    /// Executes an action in a parallel thread. 
    /// </summary>
    public void RunParallel(Action action)
    {


            if (action == null)
                throw new ArgumentNullException("action");

            lock (_lock)
            {
                if (_disposed)
                    throw new ObjectDisposedException(GetType().FullName);

                bool queued = false;
                if (_waitingThreadCount == 0)
                {
                    if (_totalThreadCount < _maxThreadCount)
                    {
                        _totalThreadCount++;

                        var thread = new Thread(_ThreadRun);
                        thread.Name = "Worker Thread";
                        thread.Start(action);
                        queued = true;
                    }
                }

                if (!queued)
                {
                    _queue.Enqueue(action);
                    Monitor.Pulse(_lock);
                }
            }

    }
    private void _ThreadRun(object firstAction)
    {
        Action action = (Action)firstAction;
        firstAction = null;
        // we always start a new thread with an action, so we get it immediately.
        // but, as we don't know what that action really holds in memory, we set
        // the initial action to null, so after it finishes and a new action is get,
        // we will let the GC collect it.

        while (true)
        {
            action();

            lock (_lock)
            {
                if (_queue.Count == 0)
                {
                    // we started waiting, so new threads don't need to be created.
                    _waitingThreadCount++;


                    while (_queue.Count == 0)
                    {

                        if (_disposed)
                            return;


                        if (_totalThreadCount > _minThreadCount)
                        {
                            _totalThreadCount--;
                            _waitingThreadCount--;
                            return;
                        }


                        action = null;
                        Monitor.Wait(_lock);
                    }

                    // we finished waiting.
                    _waitingThreadCount--;
                }

                action = _queue.Dequeue();
                // we just get a new action, and we will release the lock and return
                // to the while, where the action will be executed.
            }
        }
    }
}

I have tried to use this and the test code is as:

    PyeThreadPool MyPool;

    int x = 1;

    protected void Page_Load(object sender, EventArgs e)

    {
        MyPool = new PyeThreadPool(4, 6);

    }

    void showMessage(string message)

    {

        TxtMessage.Text = message;

    }


    protected void BtnStartThread_Click(object sender, EventArgs e)

    {

        x++;
        int arg = x;
        MyPool.RunParallel(() =>
        {
            showMessage(arg.ToString());
        });

     }

Problem is:

(1) When I execute this either in debug or release mode I do not see the result in textbox, on the other hand I see the result when I step through. What am I missing here, why I can not see the output.

(2) The RunParallel method shows only one thread even if I have set maxcount to more than 1. Is there any code logic missing or is it because the test application is simple?

Thanks !

1
  • I guess showMessage is something which runs on and requires functionallity from WinForm, or WPF? If so, these technologies don't support multithreading (though I'm not 100% sure about WPF) Commented May 1, 2014 at 15:00

2 Answers 2

1

You should have a look at SmartThreadPool library. It is one of the best alternative to ThreadPool.

Its features (copied from source link)

Smart Thread Pool is a thread pool written in C#. The implementation was first based on Stephan Toub's thread pool with some extra features, but now, it is far beyond the original. Here is a list of the thread pool features:

  • The number of threads dynamically changes according to the workload on the threads in the pool. Work items can return a value.
  • A work item can be cancelled if it hasn't been executed yet.
  • The caller thread's context is used when the work item is executed (limited).
  • Usage of minimum number of Win32 event handles, so the handle count of the application won't explode.
  • The caller can wait for multiple or all the work items to complete.
  • A work item can have a PostExecute callback, which is called as soon the work item is completed.
  • The state object that accompanies the work item can be disposed automatically.
  • Work item exceptions are sent back to the caller.
  • Work items have priority.
  • Work items group.
  • The caller can suspend the start of a thread pool and work items group.
  • Threads have priority.
  • Threads have initialization and termination events.
  • WinCE platform is supported (limited).
  • Action and Func generic methods are supported.
  • Silverlight is supported.
  • Mono is supported.
  • Performance counters (Windows and internal).
  • Work item timeout (passive).
  • Threads ApartmentState
  • Threads IsBakcground
  • Threads name template
  • Windows Phone is supported (limited)
  • Threads MaxStackSize
Sign up to request clarification or add additional context in comments.

Comments

0

The problem is you are attempting to update a UI control from a background thread. Not allowed.

You need to do a BeginInvoke or Invoke in your ShowMessage function.

2 Comments

I get this , but since this is web app and not desktop, will have to rethink approach for test application.
Ah, you can append the strings into a thread-safe collection, wait for all the threads to complete, then output the result.

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.