Jon said:
I would suggest not using the thread pool for this - you could easily
swamp it, which would make other things which try to use it less
responsive.
I would suggest you use a producer/consumer queue, and then you can
"manually" create as many threads as you want to be consumers of the
queue. This would be a sort of threadpool in itself, *just* for this
purpose. You'd have a lot more control over things that way.
See
http://www.pobox.com/~skeet/csharp/threads/deadlocks.shtml (half
way down) for some sample producer/consumer code.
Thanks for the answer.
I was now just playing around with this. Not sure if I understad it
right.
Here What I have:
using System;
using System.Collections;
using System.Threading;
public class Test
{
static CheckEmail queue;
public static int rows = 100;
static void Main()
{
queue = new CheckEmail();
new Thread(new ThreadStart(EmailChecker)).Start();
new Thread(new ThreadStart(EmailChecker)).Start();
new Thread(new ThreadStart(EmailChecker)).Start();
new Thread(new ThreadStart(EmailChecker)).Start();
new Thread(new ThreadStart(EmailChecker)).Start();
Random rng = new Random(0);
for (int i = 0; i < rows; i++)
{
Console.WriteLine("Producing {0}", i);
queue.Produce("Daniel " + i.ToString());
}
while (queue.Count > 0)
{
Console.WriteLine("There are {0} emails Waiting",
queue.Count);
Thread.Sleep(2000);
}
//Here I would like to go ahead when all EMails are processed.
}
static void EmailChecker()
{
// Make sure we get a different random seed from the
// first thread
Random rng = new Random(2);
// We happen to know we've only got 10
// items to receive
for (int i = 0; i < rows; i++)
{
object o = queue.EmailCheck();
//Process Email
Console.WriteLine("\t\t\t\tConsuming {0}", o);
Thread.Sleep(rng.Next(1000));
}
}
}
public class CheckEmail
{
readonly object listLock = new object();
Queue queue = new Queue();
private string Recipient;
public int Count
{
get { return queue.Count; }
}
public void Produce(object o)
{
lock (listLock)
{
queue.Enqueue(o);
Recipient = o.ToString();
// We always need to pulse, even if the queue wasn't
// empty before. Otherwise, if we add several items
// in quick succession, we may only pulse once, waking
// a single thread up, even if there are multiple threads
// waiting for items.
Monitor.Pulse(listLock);
}
}
public object EmailCheck()
{
lock (listLock)
{
// If the queue is empty, wait for an item to be added
// Note that this is a while loop, as we may be pulsed
// but not wake up before another thread has come in and
// consumed the newly added object. In that case, we'll
// have to wait for another pulse.
while (queue.Count == 0)
{
// This releases listLock, only reacquiring it
// after being woken up by a call to Pulse
Monitor.Wait(listLock);
}
return queue.Dequeue();
}
}
}
So I produce the queue with all emailaddresses (200'000) and then walk
trought with 5 Threads (in this exemple).
Then I wait till the que is empty. How do I know if the last Thread has
finished the work?
So I have to Write the emailaddresses in the Function EmailChecker()
back to the database right?
I also have to write the Logfile in the function EmailChecker().
How can I close the Queue to exit correctly?
I want to run this only if somone requests it by pressing the button.
Thanks for your help
Daniel