473,320 Members | 1,868 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Assign repeated tasks back to the threadpool?

I'm developing an application that gets data from 100 sources (via telnet
connections, but you can think stock quotes from a webservice if you like).

I was planning on using the thread pool (25 at a time). I know I would start
all 100 at once and as threads finish, a new thread would become available
and the next one would start.

However, I need to do this over and over (using an app that will run for
days or longer). How can I tell it, lets say when the thread handling #75 is
done and the rest are running or have completed, to start back at the
begining. I can tell the begining, next, and end through a linked list, but
I'm not clear on how to roll back to the top.

Thanks in advance,
Dave
May 4 '07 #1
5 2544
FLDaveM <FL*****@discussions.microsoft.comwrote:
I'm developing an application that gets data from 100 sources (via telnet
connections, but you can think stock quotes from a webservice if you like).

I was planning on using the thread pool (25 at a time). I know I would start
all 100 at once and as threads finish, a new thread would become available
and the next one would start.

However, I need to do this over and over (using an app that will run for
days or longer). How can I tell it, lets say when the thread handling #75 is
done and the rest are running or have completed, to start back at the
begining. I can tell the begining, next, and end through a linked list, but
I'm not clear on how to roll back to the top.
Should it wait at all between cycles? If not, you could find that if
you've got some error which occurs very quickly that you eat CPU just
by cycling round all the time.

The easiest way would probably be to make the callback which happens at
the end of the threadpool task just add it back in as a threadpool task
again. You won't necessarily keep the order (is that important?) but it
should work, and you could have a sleep there for a couple of seconds
to prevent the system from getting swamped.

One thing to watch out for though - this will basically tie up the
*whole* threadpool the whole time. That means that it will be competing
with anything else which uses the threadpool. In particular, if any of
the calls that you make to get the data end up using the threadpool
(and it's not always obvious) you could get a deadlock. I would
recommend using a custom threadpool which is completely separate from
the system one. I've got a custom threadpool in my free utility library
(http://pobox.com/~skeet/miscutil) but there are other ones around -
you'll need to work out what your requirements are.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 4 '07 #2
On 4 May, 19:56, FLDaveM <FLDa...@discussions.microsoft.comwrote:
I'm developing an application that gets data from 100 sources (via telnet
connections, but you can think stock quotes from a webservice if you like).

I was planning on using the thread pool (25 at a time). I know I would start
all 100 at once and as threads finish, a new thread would become available
and the next one would start.

However, I need to do this over and over (using an app that will run for
days or longer). How can I tell it, lets say when the thread handling #75 is
done and the rest are running or have completed, to start back at the
begining. I can tell the begining, next, and end through a linked list, but
I'm not clear on how to roll back to the top.

Thanks in advance,
Dave
Hi Dave,
I may have completely misread this, but taking your linked list
analogy try the following:

You've a linked list of 100 items. Give each node a running property
true/false. Also add an iteration property to each node.
Have an executive responsible for launching the next job and give it a
current iteration property.
When the thread ends, have it increment the node's iteration property.
The executive's MoveNext method should compare the current iteration
with the node's iteration property. If it is the same then launch a
thread, if it is current skip to next.
At the end of the list increment the executive's current iteration.
Rinse, repeat.
Also, see Jon's comments above and let us know if I've missed the
point or if not need to clarify anything.
May 4 '07 #3
On 4 May, 20:44, DeveloperX <nntp...@operamail.comwrote:
On 4 May, 19:56, FLDaveM <FLDa...@discussions.microsoft.comwrote:
I'm developing an application that gets data from 100 sources (via telnet
connections, but you can think stock quotes from a webservice if you like).
I was planning on using the thread pool (25 at a time). I know I would start
all 100 at once and as threads finish, a new thread would become available
and the next one would start.
However, I need to do this over and over (using an app that will run for
days or longer). How can I tell it, lets say when the thread handling #75 is
done and the rest are running or have completed, to start back at the
begining. I can tell the begining, next, and end through a linked list, but
I'm not clear on how to roll back to the top.
Thanks in advance,
Dave

Hi Dave,
I may have completely misread this, but taking your linked list
analogy try the following:

You've a linked list of 100 items. Give each node a running property
true/false. Also add an iteration property to each node.
Have an executive responsible for launching the next job and give it a
current iteration property.
When the thread ends, have it increment the node's iteration property.
The executive's MoveNext method should compare the current iteration
with the node's iteration property. If it is the same then launch a
thread, if it is current skip to next.
At the end of the list increment the executive's current iteration.
Rinse, repeat.

Also, see Jon's comments above and let us know if I've missed the
point or if not need to clarify anything.
Thinking about it I did misconstrue slightly. If you fire off 100 on
the first iteration, one will finish first, which will require you to
queue one more, so the above will still hold true.
Queue jobs based on the iteration property as above. I'm not near a VS
install at the moment so I can't knock out some code. If it's not
urgent I can do a little project on Tuesday (off on a little
holiday :)), but have a play with the above concept and I'm sure
you'll get it :)
May 4 '07 #4
"DeveloperX" wrote:
On 4 May, 20:44, DeveloperX <nntp...@operamail.comwrote:
On 4 May, 19:56, FLDaveM <FLDa...@discussions.microsoft.comwrote:
I'm developing an application that gets data from 100 sources (via telnet
connections, but you can think stock quotes from a webservice if you like).
I was planning on using the thread pool (25 at a time). I know I would start
all 100 at once and as threads finish, a new thread would become available
and the next one would start.
However, I need to do this over and over (using an app that will run for
days or longer). How can I tell it, lets say when the thread handling #75 is
done and the rest are running or have completed, to start back at the
begining. I can tell the begining, next, and end through a linked list, but
I'm not clear on how to roll back to the top.
Thanks in advance,
Dave
Hi Dave,
I may have completely misread this, but taking your linked list
analogy try the following:

You've a linked list of 100 items. Give each node a running property
true/false. Also add an iteration property to each node.
Have an executive responsible for launching the next job and give it a
current iteration property.
When the thread ends, have it increment the node's iteration property.
The executive's MoveNext method should compare the current iteration
with the node's iteration property. If it is the same then launch a
thread, if it is current skip to next.
At the end of the list increment the executive's current iteration.
Rinse, repeat.

Also, see Jon's comments above and let us know if I've missed the
point or if not need to clarify anything.

Thinking about it I did misconstrue slightly. If you fire off 100 on
the first iteration, one will finish first, which will require you to
queue one more, so the above will still hold true.
Queue jobs based on the iteration property as above. I'm not near a VS
install at the moment so I can't knock out some code. If it's not
urgent I can do a little project on Tuesday (off on a little
holiday :)), but have a play with the above concept and I'm sure
you'll get it :)

I truly appreciate all your suggestions. I don't completely follow (with
the executive, etc) I and don't HAVE to fire off the full list to start, I
could just assign the 1st 25 jobs and queue up the next ones. I'll give it
some thought.

Also, DeveloperX, I will be out on Monday as well, so if you had an example
on Tuesday I'd really really love to see it! I'm not the best at threads, so
any help is appreciated.

-Dave
May 4 '07 #5
- snip -
Also, DeveloperX, I will be out on Monday as well, so if you had an example
on Tuesday I'd really really love to see it! I'm not the best at threads, so
any help is appreciated.

-Dave- Hide quoted text -

- Show quoted text -
Here we go. Just paste it over a new console app and it should compile
as long as you watch out for line wrap.
In a nutshell, there's a Job class, an Executive class and a demo
class. The executive is given a bunch of jobs to process and then told
to start five of them. Each time one completes the executive is
notified and the next is kicked off.
The main demo program just runs for 15 seconds using a sleep and then
safely waits for any remaining threads to complete before shutting
down.

There are a few comments, and also various lines remmed out. For
example in the Job.AddToQueue you can see how to do start a job
through the ThreadPool and via a Thread object.

Finally there's some balancing in there. You can specify the maximum
number of threads it can consume and it will then try and stay at that
level for as long as possible.

Shout if anything doesn't make sense.

using System;
//using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Threading;

namespace RunLotsOfThreads2
{
#region test program
class Program
{
static void Main(string[] args)
{
Executive exec = new Executive();
exec.AddJob(new Job("Job 1", 1300)); //new job, name and time to
run
exec.AddJob(new Job("Job 2", 1500));
exec.AddJob(new Job("Job 3", 1700));
exec.AddJob(new Job("Job 4", 1200));
exec.AddJob(new Job("Job 5", 200));
//SetMaxThreads is 2.0 only
//ThreadPool.SetMaxThreads(3, 3); //Only got five jobs, so making
pool 3 big.
exec.ProcessStart(5);
System.Threading.Thread.Sleep(15000); //Run for n secs then close
down gracefully.
exec.CloseAll(); //that would be here :)
Console.WriteLine("done");
Console.Read();
}
}
#endregion
#region JobComplete delegate
//delegate used by event (I've broken with convention, normally it
would be sender and e params)
public delegate void JobComplete(string pReturns);
#endregion
#region Executive class
//the control class
class Executive
{
private ArrayList _jobs = new ArrayList();
//private List<Job_jobs = new List<Job>(); // dn 2 version
private int _current = 0; //current next element to process
private bool _running = false; //are we running?
private int _runningJobs = 0; //how many threads are out there.
private object lockme = new object(); //used to lock where necessary
private ManualResetEvent _mre = new ManualResetEvent(false);
//used in the tidy shut down.
private bool _closing = false; //closing down flag.
private int _maxThreads = 5;

//Waits for currently running threads to finish and closes.
public void CloseAll()
{
bool ready = false;
Console.WriteLine("Closing down");
lock (lockme)
{
_closing = true;
if (_runningJobs == 0) //it is possible there are no threads
running
{

ready = true;
}
}
if(!ready)
{
WaitForThreads();
}
foreach (Job j in _jobs)
{
//unhook. There are better ways of doing this including using
IDispose.
j.JobCompleted -= new JobComplete(pJob_JobCompleted);
}
}
private void WaitForThreads()
{
while (true)
{
if (_mre.WaitOne(1000, false)) //MRE objects allow other
interthread communication
{
break;
}
}
}
public void AddJob(Job pJob)
{
//hook up to its completion notification and add to list.
pJob.JobCompleted += new JobComplete(pJob_JobCompleted);
_jobs.Add(pJob);
}
public void ProcessStart(int pCount)
{
_running = true;
_current = 0;
ProcessNext(pCount);
}
public void ProcessNext(int pCount)
{
Job j;
//iterate through list c times looking for a currently pending
thread.
if (_running && !_closing)
{
for (int c = 0; c < pCount; c++)
{
lock(lockme)
{
j = (Job)_jobs[_current];
_current = (_current >= _jobs.Count -1 ? 0 : _current +1 );
}
if (j.Status == JobStatus.Pending || j.Status ==
JobStatus.Finished)
{
j.AddToQueue();
lock (lockme)
{
_runningJobs++;
}
}

}
}
}
private void pJob_JobCompleted(string pReturns)
{
int numberToStart;
//don't want two threads fighting for _runningJobs.
lock(lockme)
{

_runningJobs--;
numberToStart = (_maxThreads _jobs.Count ? _jobs.Count :
_maxThreads) - _runningJobs;

if (_closing)
{
if (_runningJobs == 0)
{
_mre.Set(); //Inform CloseAll we're safe to finish.
return;
}
}
}
Console.WriteLine("Balancing {0}",numberToStart);
ProcessNext(numberToStart);
}
public int MaxThreads
{
get
{
return _maxThreads;
}
set
{
_maxThreads = value;
}
}
public bool Running
{
get
{
return _running;
}
set
{
_running = value;
}
}
}
#endregion
#region JobStatus enum
//Status of job, some aren't used, but you'll get the idea.
[FlagsAttribute]
public enum JobStatus
{
None = 0,
Pending = 1,
Queued = 2,
Running = 4,
Finished = 8,
Suspended = 16
}
#endregion
#region Job class
//The job class
class Job
{
private JobStatus _status = JobStatus.Pending;
private string _name;
private int _duration = 0; //how long this will take (work is sleep
in this class)
//private Thread _thread; //used if you reinstate the non threadpool
code.
//something to lock on. Not really relevant but necessary for the
thread safe event pattern.
private object _eventLock = new object();
private event JobComplete _jobCompleted; //private event set using
the public JobComplete

public event JobComplete JobCompleted
{
add
{
lock (_eventLock) //This is required for thread safety. Exec is on
one thread so just here for illustration
{
_jobCompleted += value;
}
}
remove
{
lock (_eventLock)
{
_jobCompleted -= value;
}
}
}
public Job(string pName, int pDuration)
{
_name = pName;
_duration = pDuration;
_status = JobStatus.Pending;
}
//This is our threaded method used with QueueUserWorkItem
private void ThreadedJobMethod(object pO)
{
_status = JobStatus.Running;
Console.WriteLine("Running {0}", _name);
//do some work in this case sleep
Thread.Sleep(_duration);
//Fire event using overridable OnComplete method.
OnComplete();
}
//This is our threaded method used with Thread and ThreadStart
private void ThreadedJobMethod2()
{
ThreadedJobMethod(null);
}
//Start the thread (add to pool)
public void AddToQueue()
{
_status = JobStatus.Queued;
Console.WriteLine("Queuing {0}", _name);
//Start in thread pool
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadedJobMethod));
//Or rem out above and unrem the below to run outside of pool
//new Thread(new ThreadStart(ThreadedJobMethod2)).Start();
}
public JobStatus Status
{
get
{
return _status;
}
}
//if used as a base class, this can be overriden for extra funkiness
protected virtual void OnComplete()
{
Console.WriteLine("Completed {0}", _name);
_status = JobStatus.Finished;
if (_jobCompleted != null) //don't fire event if no one is
listening.
{
_jobCompleted(_name + " fired OnComplete"); //fire event
}
}
public string Name
{
get
{
return _name;
}
}
}
#endregion
}
May 8 '07 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: BK | last post by:
Can someone point me to a code sample that illustrates executing long running tasks (asynchronous) from a web application in ASP.NET? I assume that Web Services might come into play at some point,...
0
by: BadMotherfucker | last post by:
Hello, I want to place some threads in an arraylist. (process is always the same) But no mather what I do, my tasks take allways the last thread, never one of the first created threads. I don't...
2
by: dBNovice | last post by:
Hi all! I have 3 separate forms: Tasks, Subtasks, and Elements. All 3 is related by TaskId and Subtasks and Elements are related by SubtaskID. In the DB after I add a task, I want to be able to...
10
by: =?Utf-8?B?UHVjY2E=?= | last post by:
Hi, I'm using vs2005 and .net 2.0. I started 2 threadpool threads. How do I know when they're done with their tasks? Thanks. ThreadPool.QueueUserWorkItem(new...
3
by: Steven Blair | last post by:
I have been watching an MSDN video on the PFX Task class and have a question. Here is my scenario: TcpListener waits on incoming connections. Once a new connection is established, a new Task...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.