|Subject:||Re: sending mails in threads|
|Posted by:||Martin James (mjames_falc…@dial.pipex.com)|
|Date:||Sat, 29 Apr 2006|
"Tom" <firstname.lastname@example.org> wrote in message
> I am new to threading and have just begun with the thread demo that is
> shipped with delphi.
Oh dear... Borland threading examples are err.. 'non-optimal' :(
> I have changed the program in a first step to "fill" 100 progressbars
> "parallel". This wasn't really a hard job.
> When I now "replace" the progressbars with my "mail method" my program
> shows a strange behavior:
> When I start the program 101 threads are started (task-manager says)
You may be better off with fewer threads, queueing the work to them.
> But the mails are sent one after the other... Most of the time the
> order is:
> thread1, thread2, thread3,... sometimes thread68 starts rigth after
> thread45, then 46,47,...
> But the main problem is [the reason why I post it here] sending a mail
> takes about one second to a mail server in my 100MBit lan.
> To reach this speed I can also send all mails the "normal way".
> Below you can find the source code - this is a prototype for testing.
> [The idea is to pass an array of mail addresses and mail bodies and let
> the thread send them in a loop]
> Is this the right way ?
No. You are using 'TThread.synchronize' to call almost everything: all your
mailing is being done sequentially in the main thread. All your secondary
thread is doing is applying a complex and lengthy call mechanism, it is
worse than ineffective :(
Is it possible to split up your overall mailing job into individual tasks
that can be represented by a class that contains all data and results fields
required to perform that job and store results? A task class would probably
have only one server, but a list of addresses of a maximum size, eg. 50. If
there are more than 50 mails to be sent to a server, then multiple tasks
could be instantiated for that server, (so allowing more than one thread to
work on tasks for that server).. Once instantiated, the tasks could then be
queued to a fixed-size pool of mail threads. Each mailer thread would have
its own TidSMTP and they would all wait on the same producer-consumer queue
for task objects. The threads would pull tasks, as available, from the
queue and try to perform the mailings held within, storing success/fail in
the class for the connect and each mail. Once the task is done, the mail
thread that ran it can post the object back to the main thread so that you
can do your visual stuff to show progress on the overall job. The mailer
thread would then loop around to wait for/process another task.
You could then 'tune' the number of threads in your pool so that your
bandwidth/CPU/processors is/are best used up, no matter how many mails need
to be sent.
This approach allows the threads to work on a task without any
synchronization, since everything it needs to do the task and store results
is in the task object instance it received, not shared with the main thread
or any other task/thread.
The main thread can start the job by iterating its list of
servers/addresses/whatever, and issuing tasks to the queue. When posted
messages, with processed task objects, come into the message-handler, the
progress indiactor/s can be updated using the info in the task object,
displaying to user, logging any error messages, whatever. The task object
could then be freed, (or pooled and re-used).
sending mails in threads posted by Tom on Fri, 28 Apr 2006