Code Help for ThreadPool - c#

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 !

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

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.

Related

Managing threads using List<Thread>

I'm trying to implement a multithread in c#.
The basic idea is:
There will be a lot of thread process calling a function and every thread doesn't end in order they are called.
I want to limit maximum number of thread running.
When a thread is finished, I want to call another thread until everything is done.
So to implement this, I use a list of thread. For every second, I check if there the list is already full and if there's any thread finished its job.
Here is my code:
List<Thread> threadCompany = new List<Thread>();
List<Thread> fireThisGuy = new List<Thread>();
while (i < _finish) {
if (threadCompany.Count < _MAX_THREAD) {
Thread worker = new Thread(delegate() {
CallFunction(i);
});
threadCompany.Add(worker);
i++;
worker.Start();
}
Thread.Sleep(1000); //Wait for a while instead of keep calling if
foreach (Thread worker in threadCompany) {
if (!worker.IsAlive) {
fireThisGuy.Add(worker); //because threadCompany may not be
//modified in iteration.
}
}
foreach (Thread worker in fireThisGuy) {
threadCompany.Remove(worker);
}
fireThisGuy.Clear();
}
This works, but I don't think I'm being elegant and efficient here, how can I improve my code?
This is not the right way to solve the problem.
You don't need to keep a list of your threads, you just need to notify the application when all thread finish running.
This is a possible way to handle the problem using SynchronizationContext to notify the main thread when execution completes, without any kind of wait cycle.
public class OwnerClass
{
private SynchronizationContext syncContext;
private int count;
private int completedCount;
// This event will be raised when all thread completes
public event EventHandler Completed;
public OwnerClass() :
this(SynchronizationContext.Current)
{
}
public OwnerClass(SynchronizationContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.syncContext = context;
}
// Call this method to start running
public void Run(int threadsCount)
{
this.count = threadsCount;
for (int i = 0; i < threadsCount; ++i)
{
ThreadPool.QueueUserWorkItem(this.ThreadFunc, null);
}
}
private void ThreadFunc(object threadContext)
{
Thread.Sleep(1000); /// my long and complicated function
if (Interlocked.Increment(ref this.completedCount) >= this.count)
{
this.syncContext.Post(OnCompleted, null);
}
}
protected virtual void OnCompleted(object state)
{
var handler = this.Completed;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
If you just want to you run in a multiprocessor machne assigning a thread for each processor you can just use Parallel.For
check out TPL and/or ThreadPool.

How can I make sure that exactly one thread will do something?

I have multiple threads which add items to a lock-free queue.
The items are then processed by another thread.
In the producer threads, I need to kick off the consumer thread, but only if it's not already running or kicked off.
Specifically:
public void BeginInvoke(Action method)
{
//This runs on multiple background threads
pendingActions.Enqueue(method);
if (ProcessQueue hasn't been posted)
uiContext.Post(ProcessQueue, null);
}
private void ProcessQueue(object unused)
{
//This runs on the UI thread.
Action current;
while (pendingActions.TryDequeue(out current))
current();
}
I'm using .Net 3.5, not 4.0. :(
The easiest way is to use Semaphore. It will have a count of queue size.
I created the following class to do this:
///<summary>Ensures that a block of code is only executed once at a time.</summary>
class Valve
{
int isEntered; //0 means false; 1 true
///<summary>Tries to enter the valve.</summary>
///<returns>True if no other thread is in the valve; false if the valve has already been entered.</returns>
public bool TryEnter()
{
if (Interlocked.CompareExchange(ref isEntered, 1, 0) == 0)
return true;
return false;
}
///<summary>Allows the valve to be entered again.</summary>
public void Exit()
{
Debug.Assert(isEntered == 1);
isEntered = 0;
}
}
I use it like this:
readonly Valve valve = new Valve();
public void BeginInvoke(Action method)
{
pendingActions.Enqueue(method);
if (valve.TryEnter())
uiContext.Post(ProcessQueue, null);
}
private void ProcessQueue(object unused)
{
//This runs on the UI thread.
Action current;
while (pendingActions.TryDequeue(out current))
current();
valve.Exit();
}
Is this pattern safe?
Is there a better way to do this?
Is there a more correct name for the class?
Does this work for you?
volatile int running; //not a boolean to allow ProcessQueue to be reentrant.
private void ProcessQueue(object unused)
{
do
{
++running;
Action current;
while (pendingActions.TryDequeue(out current))
current();
--running;
}
while (pendingActions.Count != 0);
}
public void BeginInvoke(Action method)
{
pendingActions.Enqueue(method);
if (running != 0)
uiContext.Post(ProcessQueue, null);
}
Create a second Dispatcher for the consumer thread. Then, producer threads can use that dispatcher's BeginInvoke() method to send data to the consumer thread. The Dispatcher's queue takes the place of your pendingActions queue, and ensures that the consumer thread is only processing one work item at a time.
Rather than having the producer threads try to coordinate starting and stopping the consumer thread, just start the consumer thread before any producers have been started, and let it sit idle. The Dispatcher should automatically take care of waking it up when needed.

Implementing a thread queue/wait, how?

I have a timer calling a function every 15 minutes, this function counts the amount of lines in my DGV and starts a thread for each lines (of yet another function), said thread parse a web page which can take anywhere from 1 second to 10 second to finish.
Whilst it does work fine as it is with 1-6 rows, anymore will cause the requests to time-out.
I want it to wait for the newly created thread to finish processing before getting back in the loop to create another thread without locking the main UI
for (int x = 0; x <= dataGridFollow.Rows.Count - 1; x++)
{
string getID = dataGridFollow.Rows[x].Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
Thread t = new Thread(new ParameterizedThreadStart(UpdateLo));
t.Start(ID);
// <- Wait for thread to finish here before getting back in the for loop
}
I have googled a lot in the past 24 hours, read a lot about this specific issue and its implementations (Thread.Join, ThreadPools, Queuing, and even SmartThreadPool).
It's likely that I've read the correct answer somewhere but I'm not at ease enough with C# to decypher those Threading tools
Thanks for your time
to avoid the UI freeze the framework provide a class expressly for these purposes: have a look at the BackgroundWorker class (executes an operation on a separate thread), here's some infos : http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://msdn.microsoft.com/en-us/magazine/cc300429.aspx
Btw looks if I understand correctly you don't want to parallelize any operation so just wait for the method parsing the page to be completed. Basically for each (foreach look) row of your grid you get the id and call the method. If you want to go parallel just reuse the same foreach loop and add make it Parallel
http://msdn.microsoft.com/en-us/library/dd460720.aspx
What you want is to set off a few workers that do some task.
When one finishes you can start a new one off.
I'm sure there is a better way using thread pools or whatever.. but I was bored so i came up with this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Threading;
namespace WorkerTest
{
class Program
{
static void Main(string[] args)
{
WorkerGroup workerGroup = new WorkerGroup();
Console.WriteLine("Starting...");
for (int i = 0; i < 100; i++)
{
var work = new Action(() =>
{
Thread.Sleep(1000); //somework
});
workerGroup.AddWork(work);
}
while (workerGroup.WorkCount > 0)
{
Console.WriteLine(workerGroup.WorkCount);
Thread.Sleep(1000);
}
Console.WriteLine("Fin");
Console.ReadLine();
}
}
public class WorkerGroup
{
private List<Worker> workers;
private Queue<Action> workToDo;
private object Lock = new object();
public int WorkCount { get { return workToDo.Count; } }
public WorkerGroup()
{
workers = new List<Worker>();
workers.Add(new Worker());
workers.Add(new Worker());
foreach (var w in workers)
{
w.WorkCompleted += (OnWorkCompleted);
}
workToDo = new Queue<Action>();
}
private void OnWorkCompleted(object sender, EventArgs e)
{
FindWork();
}
public void AddWork(Action work)
{
workToDo.Enqueue(work);
FindWork();
}
private void FindWork()
{
lock (Lock)
{
if (workToDo.Count > 0)
{
var availableWorker = workers.FirstOrDefault(x => !x.IsBusy);
if (availableWorker != null)
{
var work = workToDo.Dequeue();
availableWorker.StartWork(work);
}
}
}
}
}
public class Worker
{
private BackgroundWorker worker;
private Action work;
public bool IsBusy { get { return worker.IsBusy; } }
public event EventHandler WorkCompleted;
public Worker()
{
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(OnWorkerDoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnWorkerRunWorkerCompleted);
}
private void OnWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (WorkCompleted != null)
{
WorkCompleted(this, EventArgs.Empty);
}
}
public void StartWork(Action work)
{
if (!IsBusy)
{
this.work = work;
worker.RunWorkerAsync();
}
else
{
throw new InvalidOperationException("Worker is busy");
}
}
private void OnWorkerDoWork(object sender, DoWorkEventArgs e)
{
work.Invoke();
work = null;
}
}
}
This would be just a starting point.
You could start it off with a list of Actions and then have a completed event for when that group of actions is finished.
then at least you can use a ManualResetEvent to wait for the completed event.. or whatever logic you want really.
Call a method directly or do a while loop (with sleep calls) to check the status of the thread.
There are also async events but the would call another method, and you want to continue from the same point.
I have no idea why the requests would timeout. That sounds like a different issue. However, I can make a few suggestions regarding your current approach.
Avoid creating threads in loops with nondeterministic bounds. There is a lot of overhead in creating threads. If the number of operations is not known before hand then use the ThreadPool or the Task Parallel Library instead.
You are not going to get the behavior you want by blocking the UI thread with Thread.Join. The cause the UI to become unresponsive and it will effectively serialize the operations and cancel out any advantage you were hoping to gain with threads.
If you really want to limit the number of concurrent operations then a better solution is to create a separate dedicated thread for kicking off the operations. This thread will spin around a loop indefinitely waiting for items to appear in a queue and when they do it will dequeue them and use that information to kick off an operation asynchronously (again using the ThreadPool or TPL). The dequeueing thread can contain the logic for limiting the number of concurrent operations. Search for information regarding the producer-consumer pattern to get a better understand of how you can implement this.
There is a bit of a learning curve, but who said threading was easy right?
If I understand correctly, what you're currently doing is looping through a list of IDs in the UI thread, starting a new thread to handle each one. The blocking issue you're seeing then could well be that it's taking too many resources to create unique threads. So, personally (without knowing more) would redesign the process like so:
//Somewhere in the UI Thread
Thread worker = new Thread(new ParameterizedThreadStart(UpdateLoWorker));
worker.Start(dataGridFollow.Rows);
//worker thread
private void UpdateLoWorker(DataRowCollection rows)
{
foreach(DataRow r in rows){
string getID = r.Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
UpdateLo(ID);
}
}
Here you'd have a single non-blocking worker which sequentially handles each ID.
Consider using Asynchronous CTP. It's an asynch pattern Microsoft recently released for download. It should simplify asynch programming tremendouesly. The link is http://msdn.microsoft.com/en-us/vstudio/async.aspx. (Read the whitepaper first)
Your code would look something like the following. (I've not verified my syntax yet, sorry).
private async Task DoTheWork()
{
for(int x = 0; x <= dataGridFollow.Rows.Count - 1; x++)
{
string getID = dataGridFollow.Rows[x].Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
task t = new Task(new Action<object>(UpdateLo), ID);
t.Start();
await t;
}
}
This method returns a Task that can be checked periodically for completion. This follows the pattern of "fire and forget" meaning you just call it and presumably, you don't care when it completes (as long as it does complete before 15 minutes).
EDIT
I corrected the syntax above, you would need to change UpdateLo to take an object instead of an Int.
For a simple background thread runner that will run one thread from a queue at a time you can do something like this:
private List<Thread> mThreads = new List<Thread>();
public static void Main()
{
Thread t = new Thread(ThreadMonitor);
t.IsBackground = true;
t.Start();
}
private static void ThreadMonitor()
{
while (true)
{
foreach (Thread t in mThreads.ToArray())
{
// Runs one thread in the queue and waits for it to finish
t.Start();
mThreads.Remove(t);
t.Join();
}
Thread.Sleep(2000); // Wait before checking for new threads
}
}
// Called from the UI or elsewhere to create any number of new threads to run
public static void DoStuff()
{
Thread t = new Thread(DoCorestuff);
t.IsBackground = true;
mActiveThreads.Add(t);
}
public static void DoStuffCore()
{
// Your code here
}

CPU usage goes to almost 100% with Async queue processing

I have an async queue processor that has a Run method which keeps running with a pause of 100ms. This code results in CPU usage of almost 100%. following the thr code of 'Run' method of this async queue processor.
private void Run()
{
while (true)
{
if (q.Count != 0)
{
ServiceMessage msg = (ServiceMessage)synchQ.Dequeue();
OnHeartBeat(msg.Args);
}
PauseTrigger.WaitOne(100, false);
}
}
Please let me know if there is something wrong that I am doing.
If queue is empty and PauseTrigger is set this will spin and use 100% CPU.
If you are using .NET 4 then BlockingCollection provides a much nicer way to handle queueing and dequeing.
A simple fix would be to try Thread.Sleep (100); rather than PauseTrigger.WaitOne(100)
If it doesn't matter for you which thread OnHeartBeat is called on you can use this class.
public class ProcessingQueue<T>
{
private readonly object _lock = new object();
private readonly Queue<T> _queue = new Queue<T>();
private readonly Action<T> _workMethod;
private bool _pumpIsAlive;
private void Pump()
{
while (true)
{
lock (this._lock)
{
item = this._queue.Dequeue();
}
this._workMethod(item);
lock (this._lock)
{
if (this._queue.Count == 0)
{
this._pumpIsAlive = false;
break;
}
}
}
/// <summary>
/// Pushes an item onto the processing the queue to be handled at an indeterminate time.
/// </summary>
/// <param name="item">The item to push onto the queue.</param>
public void Push(T item)
{
lock (this._lock)
{
this._queue.Enqueue(new Containter(item));
this.StartPump();
}
}
private void StartPump()
{
lock (this._lock)
{
if (!this._pumpIsAlive)
{
this._pumpIsAlive= true;
ThreadPool.QueueUserWorkItem(o => this.Pump());
}
}
}
which you could then use like:
var q = new ProcessingQueue<ServiceMessage> ( sm => OnHeartBeat(sm.args));
q.Push (new ServiceMessage (someArgs));
OnHeartBeat(msg.Args) takes longer than 100ms to complete?
Why not run your code in a profiler to find out where the CPU cycles are being spent?
See this question: Any Good Free .NET Profiler?
2 things... why are you dequeueing synchQ while checking for q.count?
Try putting a counter and see if you are running into an infinite loop because of synchQ and q.count check

Background worker synchronization

Lets say I have a class that is supposed to generate some ID (for example GUID) for me. Now unfortunately the ID generation is a somewhat long process and if I need a hundred of those I run into a problem of significant slowdowns. In order to avoid those, I keep a queue of pre-generated ID, and when this queue starts to run down on them I use the BackgroundWorker to generate new ones and place them in the queue. But there are some problems I've run into. The biggest one at the moment is how to make sure that in case the queue compleatelly runs out on IDs the main thread waits for the BackroundWorker to generate and place them in the queue. Heres the code that I have at the moment.
public class IdGenerator
{
private Queue<string> mIds = new Queue<string>();
private BackgroundWorker mWorker = new BackgroundWorker();
private static EventWaitHandle mWaitHandle = new AutoResetEvent(false);
public IdGenerator()
{
GenerateIds();
this.mWorker.DoWork += new DoWorkEventHandler(FillQueueWithIds);
}
private void GenerateIds()
{
List<string> ids = new List<string>();
for (int i = 0; i < 100; i++ )
{
ids.Add(Guid.NewGuid().ToString());
}
lock (this.mIds)
{
foreach (string id in ids)
{
this.mIds.Enqueue(id);
}
}
}
public string GetId()
{
string id = string.Empty;
lock (this.mIds)
{
if (this.mIds.Count > 0)
{
id = this.mIds.Dequeue();
}
if (this.mIds.Count < 100)
{
if (!this.mWorker.IsBusy)
{
this.mWorker.RunWorkerAsync();
}
}
}
if (this.mIds.Count < 1)
{
mWaitHandle.WaitOne();
}
return id;
}
void FillQueueWithIds(object sender, DoWorkEventArgs e)
{
GenerateIds();
mWaitHandle.Set();
}
}
Obviously it doesn't work correctly. It seems that I have a problem with proper timing for calling WaitOne and Set methods. And sometimes the IsBusy property returns true even though the worker has already completed his work.
EDIT:
Its a WinForm and I'm required to use .NET 2.0
The problem you have is the classic Producer-Consumer problem. Take a look at http://en.wikipedia.org/wiki/Producer-consumer_problem
A simple explanation is that you will have two threads. One will be the producer (the GUID generator) and the other will be the consumer.
You will keep these threads in synch through the use of semaphores. The semaphore will be the responsible to stop the producer when the queue is full and to stop the consumer when it is empty.
The process is all very well explained at the Wikipedia article and I bet you can find a basic implementation of Producer-Consumer in c# on the internet.
In .NET 4 you can use the BlockingCollection<T> and more generically IProducerConsumerCollection<T>
Here's an example of 2 tasks, one adding and the other taking, using it.
http://msdn.microsoft.com/en-us/library/dd997306.aspx
There are some bugs related to thread sync, see in changed code below.
When you apply lock sync to queue pay attention to put under lock all uses of queue.
I've changed GetId method to probe for new ids if there are none.
public class IdGenerator
{
private Queue<string> mIds = new Queue<string>();
private BackgroundWorker mWorker = new BackgroundWorker();
private static EventWaitHandle mWaitHandle = new AutoResetEvent(false);
public IdGenerator()
{
GenerateIds();
this.mWorker.DoWork += new DoWorkEventHandler(FillQueueWithIds);
}
private void GenerateIds()
{
List<string> ids = new List<string>();
for (int i = 0; i < 100; i++ )
{
ids.Add(Guid.NewGuid().ToString());
}
lock (this.mIds)
{
foreach (string id in ids)
{
this.mIds.Enqueue(id);
}
}
}
public string GetId()
{
string id = string.Empty;
//Indicates if we need to wait
bool needWait = false;
do
{
lock (this.mIds)
{
if (this.mIds.Count > 0)
{
id = this.mIds.Dequeue();
return id;
}
if (this.mIds.Count < 100 && this.mIds.Count > 0)
{
if (!this.mWorker.IsBusy)
{
this.mWorker.RunWorkerAsync();
}
}
else
{
needWait = true;
}
}
if (needWait)
{
mWaitHandle.WaitOne();
needWait = false;
}
} while(true);
return id;
}
void FillQueueWithIds(object sender, DoWorkEventArgs e)
{
GenerateIds();
mWaitHandle.Set();
}
}
Your main code (presumably WinForms) calls mWaitHandle.WaitOne() at a certain point. At that moment the Messagepump is blocked and the Bgw will be unable to call its Completed event. That means the IsBusy flag remain true: deadlock.
Similar issues can arise if code inside DoWork throws an exception.
Edit:
I would think that you could solve most problems by using a ThreadPool thread to replace the Bgw. And a simple volatile bool isbusy flag.
OK, heres the final solution I went with. This one doesn't use the BackgroundWorker, but it works. Thanks to Edu who pointed to the Producer-Consumer problem. I used the example provided by MSDN located here.

Categories

Resources