How many threads to create?

S

SamIAm

Hi am creating a email application that needs to mail out a very large
amount of emails. I have created a multithreaded c# application that using
message queuing. I have created a threadpool of 5 threads and each thread
checks the queue, receives the message and sends an email. How do I
determine the right amount of threads to create?

Thanks,

S
 
M

Mr.Tickle

42 :D

I use for my mailing purposes Glock easy mail pro. Not spam , but for
testing mailers etc and so on.
 
S

SamIAm

Ha-ha

Nope thankfully its not spam! It is part of a new application we are
launching and has the potential to have 4 000 000+ members who need to
receive a weekly email.

S
 
S

SamIAm

Thanks for all the replies.

Here is some sample code I have. Feel free to take a look and make any
comments:
The Form:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Messaging;
using System.Threading;

using CardFinder;

namespace TestHandler
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.GroupBox grpSendMails;
private System.Windows.Forms.TextBox txtMailCount;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button btnReceiveMail;
private System.Windows.Forms.Button btnSendMail;
private System.Windows.Forms.TextBox txtTo;
private System.Windows.Forms.GroupBox grpReceive;
private System.Windows.Forms.TextBox txtThreadCount;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnReceiveMail = new System.Windows.Forms.Button();
this.grpSendMails = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.txtMailCount = new System.Windows.Forms.TextBox();
this.btnSendMail = new System.Windows.Forms.Button();
this.txtTo = new System.Windows.Forms.TextBox();
this.grpReceive = new System.Windows.Forms.GroupBox();
this.txtThreadCount = new System.Windows.Forms.TextBox();
this.grpSendMails.SuspendLayout();
this.grpReceive.SuspendLayout();
this.SuspendLayout();
//
// btnReceiveMail
//
this.btnReceiveMail.Location = new System.Drawing.Point(248, 48);
this.btnReceiveMail.Name = "btnReceiveMail";
this.btnReceiveMail.TabIndex = 1;
this.btnReceiveMail.Text = "Recieve";
this.btnReceiveMail.Click += new
System.EventHandler(this.btnReceiveMail_Click);
//
// grpSendMails
//
this.grpSendMails.Controls.AddRange(new System.Windows.Forms.Control[] {
this.txtTo,
this.label1,
this.txtMailCount,
this.btnSendMail});
this.grpSendMails.Location = new System.Drawing.Point(16, 16);
this.grpSendMails.Name = "grpSendMails";
this.grpSendMails.Size = new System.Drawing.Size(384, 112);
this.grpSendMails.TabIndex = 2;
this.grpSendMails.TabStop = false;
this.grpSendMails.Text = "Send Mails";
//
// label1
//
this.label1.Location = new System.Drawing.Point(32, 64);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(80, 24);
this.label1.TabIndex = 3;
this.label1.Text = "No of mails:";
//
// txtMailCount
//
this.txtMailCount.Location = new System.Drawing.Point(120, 64);
this.txtMailCount.Name = "txtMailCount";
this.txtMailCount.Size = new System.Drawing.Size(112, 20);
this.txtMailCount.TabIndex = 2;
this.txtMailCount.Text = "100000";
//
// btnSendMail
//
this.btnSendMail.Location = new System.Drawing.Point(240, 64);
this.btnSendMail.Name = "btnSendMail";
this.btnSendMail.TabIndex = 1;
this.btnSendMail.Text = "Send";
this.btnSendMail.Click += new
System.EventHandler(this.btnSendMail_Click);
//
// txtTo
//
this.txtTo.Location = new System.Drawing.Point(120, 32);
this.txtTo.Name = "txtTo";
this.txtTo.Size = new System.Drawing.Size(112, 20);
this.txtTo.TabIndex = 4;
this.txtTo.Text = "(e-mail address removed)";
//
// grpReceive
//
this.grpReceive.Controls.AddRange(new System.Windows.Forms.Control[] {
this.txtThreadCount,
this.btnReceiveMail});
this.grpReceive.Location = new System.Drawing.Point(16, 136);
this.grpReceive.Name = "grpReceive";
this.grpReceive.Size = new System.Drawing.Size(384, 128);
this.grpReceive.TabIndex = 3;
this.grpReceive.TabStop = false;
this.grpReceive.Text = "Receive Mails";
//
// txtThreadCount
//
this.txtThreadCount.Location = new System.Drawing.Point(136, 48);
this.txtThreadCount.Name = "txtThreadCount";
this.txtThreadCount.TabIndex = 2;
this.txtThreadCount.Text = "5";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(416, 317);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.grpReceive,
this.grpSendMails});
this.Name = "Form1";
this.Text = "Form1";
this.grpSendMails.ResumeLayout(false);
this.grpReceive.ResumeLayout(false);
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

/// <summary>
/// Creates test emails
/// </summary>
private void btnSendMail_Click(object sender, System.EventArgs e)
{
// Create a new mailer instance
Mailer mailer = new Mailer();
try
{
// Create x number of test messages in the queue
mailer.SendMail(txtTo.Text.Trim(),
Convert.ToInt32(txtMailCount.Text.Trim()));
MessageBox.Show("Done");
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}

/// <summary>
/// Starts threads to create emails from the messages in the queue
/// </summary>
private void btnReceiveMail_Click(object sender, System.EventArgs e)
{
// How many threads
int THREAD_COUNT = Convert.ToInt32(txtThreadCount.Text.Trim());
int loop;
Mailer mailer = new Mailer();
Thread[] ThreadArray = new Thread[THREAD_COUNT];
// Loop through and create listener threads that process the messages in
the queue
for(loop = 0; loop < THREAD_COUNT; loop++)
{
ThreadArray[loop] = new Thread(new ThreadStart(mailer.Listen));
ThreadArray[loop].Start();
}
}
}
}

The Mailer Class:
using System;
using System.Messaging;
using System.Threading;
using System.Web.Mail;

namespace CardFinder
{
/// <summary>
/// Summary description for Mailer.
/// </summary>
public class Mailer
{

public Mailer()
{
}


public void SendMail(string Email)
{
SendMail(Email, 1);
}

/// <summary>
/// Creates messages in the queue
/// </summary>
/// <param name="Email">Email to send to</param>
/// <param name="MailCount">No of messages to create</param>
public void SendMail(string Email, int MailCount)
{
// Get the queue
MessageQueue CardFinderQueue = new
MessageQueue(@".\Private$\CardFinderMails");
// Create messages
for(int loop = 0;loop < MailCount;loop++)
{
MailMessage msg = new MailMessage();
msg.Email = Email;
CardFinderQueue.Send(msg, "Email Test");
}
}

/// <summary>
/// Processes the queue
/// </summary>
public void Listen()
{
// Get the queue
MessageQueue CardFinderQueue = new
MessageQueue(@".\Private$\CardFinderMails");
CardFinderQueue.Formatter = new XmlMessageFormatter(new Type[]
{typeof(CardFinder.MailMessage)});
Message qmsg = null;
while (true)
{
try
{
System.Threading.Thread.Sleep(100);

qmsg = CardFinderQueue.Receive(new TimeSpan(0,0,0,1));
MailMessage msg = (MailMessage)qmsg.Body;

string email = msg.Email;
SmtpMail.Send("(e-mail address removed)", email, "CardFinder Test",
"<html><body><h1>Test</h1></body></html>");
}
// Not sure what the following is for :)
catch(ThreadInterruptedException threadEx)
{
qmsg.Dispose();
CardFinderQueue.Dispose();
break;
}
catch(Exception Ex)
{
}
}
}
}
}

The MailMessage Class:
using System;

namespace CardFinder
{
/// <summary>
/// Summary description for MailMessage.
/// </summary>
public class MailMessage
{
private string _email;

public string Email
{
get
{
return _email;
}
set
{
_email = value;
}
}
}
}


Thanks

S
 
J

Jacob Gladish

The right number is going to depend on the amount of bandwidth you have
available, and how fast you want to send out messages. It's very likely that
with 5 threads, you should be able to saturate a single network interface
with 100Mbs, or at least reach near peak bandwith for you OS/Hardware
configuration. You should probably concentrate more on how you're going to
send out 4,000,000 email messages without disrupting connectivity to the
rest of the world on the network where the spaminator is located, or
gettting blacklisted by ISPs. (sorry, sending out 4,000,000 messages is spam
even if they ask for it)

FYI, 4,000,000 evenly distributed over a 10 hour peroid is about 110 per
second. If each message where say 500 bytes, that's ~ 440,000 bits per
second. or 1/2 the bandwith of a T1. It's also likely that your weekly
newsletter if going to be in html and have images, so pro-rate appropriately
for the 500 bytes. If you assumed 5K, then you're talking days to send
4,000,000 messages without several big pipes. The slickest threadpool in the
world isn't going to help.
 
J

Justin Rogers

Yes, I quickly recommend sending a LINK to your website where the newsletter
is actually hosted. Either that or you should hire an external entity to do
your mailing for you. By doing so, you'll already have their experience of
solving the various problems pointed out by Jacob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top