PatrikBMedlem sedan mars 20002 836 inlägg Hello!
har setat och labbat med att connecta direkt mot SMTP-servern för att skicka en hel del mail (email-lista) för en kunds räkning där deras hotell inte erbjuder listserv-funktioner.
När jag körde skicket av alla mail adresser (ca 500 st) från en asp sida med ett enkelt anrop tog det ca 5 minuter att skicka alla dessa.
Alldeles för segt enligt mig och började kika på att skicka allt genom att skapa en ny tråd för detta.
Vips! .... nu flög det iväg. De ca 500 mailen skickades på mindre än 1 minut.
Nu till själva frågan.
Har tråden som aspx-sidan körs i mer "overhead" än om man skapar en ny tråd där enbart skicken av alla mailen körs?
kod 1 som tar ca 5 minuter att köra:
Public Function SendBulkMail(ByVal email as MailMessage, ByVal recipients As ArrayList) As String
Try
If (recipients.Count > -1) Then
Me.Connect()
'## -- send helo to server --
SendCommand("HELO " + System.Net.Dns.GetHostName() + ControlChars.CrLf)
'## -- loop through all mail in list .
Dim i as Integer
For i = 1 TO (recipients.Length - 1)
email.ToMail = recipients.Item(i)
SendCommand("MAIL " + email.FromMail + ControlChars.CrLf)
SendCommand("RCPT " + email.ToMail + ControlChars.CrLf)
Dim _mailHeader As String = ""
_mailHeader += email.FromMail + ControlChars.CrLf
_mailHeader += email.ToMail + ControlChars.CrLf
_mailHeader += email.Subject + ControlChars.CrLf
_mailHeader += "Content-type: text/html; charset=""ISO-8859-1""" + ControlChars.CrLf
SendCommand("DATA" + ControlChars.CrLf + _mailHeader + email.Body + ControlChars.CrLf + "." + ControlChars.CrLf)
Next _emailCnt
Me.Disconnect()
Return "Mail sent successfully to: " + email.ToMail
Else
Return "No recipients given as input"
End If
Catch Ex As Exception
Return "ERROR: " + Ex.Message
End Try
End Function
Kod 2, som tar mindre än 1 minut att köra (samma antal mail):
Public Function Send() As String
Try
Dim _sendStart As New ThreadStart(AddressOf SendToAll)
Dim _sendThread As New Thread(_sendStart)
_sendThread.Start()
Return "All mail sent."
Catch Ex As Exception
Return "ERROR: Send() - " + Ex.Message
End Try
End Function
Private Sub SendToAll()
Try
If (_recipients.Count > -1) Then
'## -- send mail to all recipients --
Dim i As Integer
For i = 0 TO (_recipients.Count - 1)
_email.ToMail = _recipients.Item(i)
Dim _smtp As New SMTP("xxx.xxx.xxx.xxx",25)
_smtp.Send(_email)
Next
End If
Catch Ex As Exception
Throw Ex
End Try
End Sub
Varför är det så?
Bara nyfiken ..... rent allmänt och kanske kan detta hjälpa en del andra ...
cya,
/PatrikB
GladhMedlem sedan maj 20012 812 inlägg Public Function Send() As String
Try
Dim _sendStart As New ThreadStart(AddressOf SendToAll)
Dim _sendThread As New Thread(_sendStart)
_sendThread.Start()
Return "All mail sent."
Catch Ex As Exception
Return "ERROR: Send() - " + Ex.Message
End Try
End Function
Tyvärr fungerar inte din kod så som du tror att den gör det. När du gör:
_sendThread.Start()
Så skapas en ny tråd och din SendToAll() funktion kommer att anropas och köras i din nya tråd.
Din main tråd kommer dock fortsätta att köras och köra nästa rad i funktionen Send()
Return "All mail sent."
Kommer alltså att köras INNAN alla mail är ivägskickade. Vilket betyder att när din ASPX sida är färdig exekverad så ligger din tråd fortfarande i backgrunden och skickar iväg mail...
Du borde kunna göra en Thread.Join() precis efter din _sendThread.Start()
och se hur lång tid sidan tar, eftersom Join() methoden skall vänta tills din nya tråd är färdig innan huvudtråden fortsätter sin exekvering.
Du har helt rätt i att trådning kommer att snabba upp utsändningen av mail, men då skall varje mail skickas i EN EGEN tråd, alltså inte skicka alla mail i en tråd utan du skapar en ny tråd för varje mail. Detta kommer dock ge en massa overhead som inte är så bra, eftersom det kostar prestanda att skapa och släppa en tråd. Det finns därför i .NET en treadpool som man kan använda sig av, och om man gör Asynchronaanrop så använder man sig av denna pool. Så läs på mer om trådar, så kommer du hitta många roligheter och en hel del konstigheter också, eftersom man måste säkra upp sin kod så att endast EN tråd får komma åt delad information åt gången, felhanteringen är också lite speciell, eftersom ett fel i en tråd inte kastas tillbaka till huvudtråden på det sätt som du tror, alltså får du ett fel i en tråd så är det inte säkert att din applikation stoppas, det kan vara så att det endast är tråden som stoppas och du får aldrig reda på det i din huvudtråd :)
- M
PatrikBMedlem sedan mars 20002 836 inlägg Det med return vet jag .... lite skräp som ligger kvar ... testade bara rent "frankt" att skapa en ny tråd. Det är på inga vis färdigt utan bara testning .... och det var lite av en "bakgrunds process" som jag ville få fram så att inte aspx-sidan gör en timeout.
Dock är det så här att jag har admin på mail-servern och kan där se prestandan (genom loggning) och där visade det sig att det med att skapa en ny tråd som skickar iväg alla mail, inte en tråd per mail, var 500% snabbare ..... har gjort flera olika körningar och alla har visat samma resultat ....
Ska dock läsa på mer om trådar, det var som sagt bara en "vild chansning" med att skapa en ny tråd ... som visade sig ge klart bättre prestanda ...
Lite tips om vart man kan hitta info om "trådar"?
cya,
/PatrikB
GladhMedlem sedan maj 20012 812 inlägg Varför det blir snabbare att skicka allt i en tråd vet jag inte. Antar väl precis som du att det ligger en massa overhead i ASPX tråden så fall.
Information om trådar finns dels i hjälpen för VS.NET dels på MSDN dels här: http://www.google.dk/search?q=%2B"Thread"+%2B"C%23"&ie=UTF-8&oe=UTF-8&hl=da&meta=
- M
Använd w3JMail Professional istället. Där finns ínbyggda funktioner för att fullkomligt spruta ut mail. Du kan få w3JMail att fungera i ASP.NET också.
PatrikBMedlem sedan mars 20002 836 inlägg Som sagt, nu finns inte w3JMail installerat på den servern + om det fanns det så tror jag inte att användarna har rätt till pick-up-foldern på servern för att kunna använda den funktionaliteten i w3JMail.
Hade man haft det, en pickupfolder, så går det ju hur lätt som helst att "fixa till" en lista som sprutar ut mailen ... tyvärr är så inte fallet nu.
Endast CDONTS kan användas vilket inte är speciellt lyckat vid "mass-mail"/epost-listor med mellan 500 - 1500 medlemmar
En annan aspekt på det hela.
Vill inte vara beroende av vad som finns installerat på en server, för när nästa kund vill ha något så finns säkerligen inte dessa grejjer installerad på den kundens server eller möjlighet att installera det som behövs.
cya,
/PatrikB
BrimbaMedlem sedan dec. 19995 875 inlägg Bygg en massmailer-service som du lägger på servern. Den kan sedan exempelvis ligga och läsa av en databastabell emellanåt. När den ser en post i tabellen så itererar den alla poster och för varje post skickar den ett mail, och sedan kör du en delay (för att inte belasta servern).
Du kan ju ställa in att den kollar efter mail i tabellen var 15:e minut eller något...
PatrikBMedlem sedan mars 20002 836 inlägg Vad menar du med "service"?
En "vanlig" windows-tjänst?
Något sådant tror jag inte ett vanligt webbhotell tillåter.
Koden ska kunna köras UTAN att behöva ha tillgång till servern, dvs koden ska kunna köras på en vanlig webbhotells-server.
Annars, då hade detta redan varit fixat med att starta en enkel SMTP-tjänst och sedan parsa ned mail till PickUp-foldern. TJOFF!!! så var en jädrans massa mail ivägskickade :e
cya,
/PatrikB