I have an application that takes too long to run, and I want to introduce threading / parallelization / whatever.
Specifically, the code retreives several thousand mails, then sends them. Today, the code looks like this (a bit simplified) :
Dim mails = centreInteretService.GetEmails()
For Each m in mails
m.Body = GetMailContent(m)
If MailSendable(m) Then
SendMail(m)
End If
Next
I want to try sending multiple mails in parallel. I would like to try with 2 threads in parallel. More specifically, I would want to put the whole loop in a thread (getmailcontent + sendmail).
I thought of something like this :
Dim mails1 As New List(Of MailSerialiserCI)
Dim mails2 As New List(Of MailSerialiserCI)
Dim nbFirstList As Integer = CInt(Math.Ceiling(nbTotal / 2))
mails1 = mails.Take(nbFirstList)
mails2 = mails.Skip(nbFirstList)
Dim smt1 As New MailSender.MailSenderThreaded()
smt1.mails = mails1
smt1.nbTotal = nbTotal
Dim threadMails1 As ThreadStart = New ThreadStart(AddressOf smt1.SendMails)
Dim th1 As Thread = New Thread(AddressOf threadMails1)
th1.Start()
Dim smt2 As New MailSender.MailSenderThreaded()
smt2.mails = mails2
smt2.nbTotal = nbTotal
Dim threadMails2 As ThreadStart = New ThreadStart(AddressOf smt2.SendMails)
Dim th2 As Thread = New Thread(AddressOf threadMails2)
th2.Start()
And MailSenderThreaded is like this :
Public Class MailSenderThreaded
Public mails As List(Of MailSerialiserCI)
Public nbTotal As Integer
Public Sub SendMails()
LoopMails(Me.mails, Me.nbTotal)
End Sub
End Class
But the lines with New Thread(AdressOf x)
give me an error : no applicable function x matching delegate System.Threading.ParameterizedThreadStart
.
I tried searching here and there, but I can only find either solutions that require a lot more knowledge than what I have ; or threading basics ; or .NET 4 stuff, but we are still in .NET 3.5...
Do you have a simple solution that I could try ?
Thanks
If the body of your loop is thread-safe, you could just use Parallel.ForEach
In C#, it would look like this:
var mails = centreInteretService.GetEmails();
Parallel.ForEach( mails, new ParallelOptions { MaxDegreeOfParallelism = 2 }, m =>
{
m.Body = GetMailContent(m);
if ( MailSendable(m) ) SendMail(m);
}
);
EDIT: .NET 3.5!
I think this is about the simplest solution in .NET 3.5:
( Sorry it's in C# - I don't know VB. I hope you can read it. )
...
List<Mail> mails = centreInteretService.GetEmails();
var mailer = new Mailer( mails );
mailer.Run();
...
public class Mailer
{
const int THREAD_COUNT = 2;
List<Thread> _Threads = new List<Thread>();
List<Mail> _List = null;
int _Index = -1;
public Mailer( List<Mail> list )
{
_List = list;
}
public void Run()
{
for ( int i = 0 ; i < THREAD_COUNT ; i++ )
{
_Threads.Add( StartThread() );
}
foreach ( var thread in _Threads ) thread.Join();
}
Thread StartThread()
{
var t = new Thread( ThreadMain );
t.Start();
return t;
}
void ThreadMain()
{
for ( ; ; )
{
int index = Interlocked.Increment( ref _Index );
if ( index >= _List.Count ) return;
ThreadWork( _List[ index ] );
}
}
void ThreadWork( Mail mail )
{
mail.Body = GetMailContent(mail);
if ( MailSendable(mail) ) SendMail(mail);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With