#vb.net #sendmail #smtpclient
#vb.net #отправка почты #smtpclient
Вопрос:
Вопрос1:
Я отправляю сообщение с помощью SendAsync:
Я отправляю огромные электронные письма, и я получаю слишком большую задержку в обратном вызове сообщения: client.Отправка завершена
Электронное письмо отправляется асинхронно, но обратный вызов выглядит последовательным, похоже, что только один поток отправляет и получает электронные письма.
например, если обратный вызов сообщения задерживается на 1 секунду, чтобы вернуться с почтовых серверов, и я отправляю 20 электронных писем, это задержит около 20 секунд на все сообщения, которые должны быть доставлены и завершены.
Итак, похоже, что есть только один поток, отправляющий сообщения в последовательной очереди…
Если SendAsync внутренне работает с пулом потоков, есть ли способ изменить количество потоков в этом пуле, максимальное количество потоков и другие вещи, связанные с пулами потоков?
Вопрос2:
Еще один связанный с этим вопрос о SendMailAsync: https://docs.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient.sendmailasync?view=netframework-4.7.2
Внутренне SendMailAsync выполняет то же самое, что и SendAsync, несмотря на то, что дизайн кода немного отличается?
В чем реальная разница между SendAsync и SendMailAsync; должно ли это решить проблему, о которой я говорю в вопросе 1?
КОД
Dim counter = 0
Public Async Function SendEmail(email As String, bodystuff As String) As Task
Dim smtp As New SmtpClient() '"email-smtp.us-west-3.amazonaws.com")
Dim hostloginpass = "email-smtp.us-west-3.amazonaws.com, AKDKJDAKJ2SKJMSDKJ2,AK2KD298;kdj2kjdkjaiuwkmp2KKK2098K2la97ksjNW,Test_Site"
smtp.Host = cla_util.sGetToken(hostloginpass, 1, ",")
smtp.Port = 587
smtp.Credentials = New System.Net.NetworkCredential(getTokenFromArr(hostloginpass, 2, ","), getTokenFromArr(hostloginpass, 3, ","))
smtp.EnableSsl = true
Dim from As New MailAddress("contact@myserver.com", "Info", System.Text.Encoding.UTF8)
Dim [to] As New MailAddress(email)
Dim message As New MailMessage(from, [to])
message.Body = String.Format("The message I want to send is to this <b>contact: {0}{1}</b>", vbCrLf, bodystuff)
message.IsBodyHtml = True
message.BodyEncoding = System.Text.Encoding.UTF8
message.Subject = "Test email subject"
message.SubjectEncoding = System.Text.Encoding.UTF8
'commented -> Await smtp.SendMailAsync(message)
smtp.SendMailAsync(message)
counter = counter 1
System.Console.WriteLine("Counter -> " amp; counter)
End Function
Dim _isCompleted
Dim _timing
Dim Tasks As New ArrayList
Public Async Sub StartEmailRun()
Try
Dim sWatch As New Stopwatch()
sWatch.Start()
For i = 0 To 50
Tasks.Add(SendEmail("a_test_email@gmail.com", "email test"))
Next
Console.WriteLine("SETP OUT OF THE SENDING")
_isCompleted = True
sWatch.Stop()
_timing = sWatch.ElapsedMilliseconds
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Public Async Sub StartEmailRun2()
Try
Dim sWatch As New Stopwatch()
sWatch.Start()
For i = 0 To 50
Dim thread as New Thread(
Sub()
SendEmail("a_test_email@gmail.com", "email test")
End Sub
)
thread.Start()
Next
Console.WriteLine("SETP OUT OF THE SENDING")
_isCompleted = True
sWatch.Stop()
_timing = sWatch.ElapsedMilliseconds
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Комментарии:
1. Они используют тот же метод под капотом, но второй возвращает задачу из a
TaskCompletionSource
. Это ожидаемо. В первом используется aSendOrPostCallback
. Считайте это управляемым событиями. Это отличается от того, как вы можете обрабатывать пул этих объектов. Используя этотSendMailAsync
метод, вы можете запустить список задач, используя этотSendAsync
метод, вы можете прикрепить обработчик кSendCompleted
событию ваших объектов SmtpClient. Вероятно, его проще использовать, если вы не знакомы с объединением задач.2. «Итак, похоже, что есть только один поток, отправляющий сообщения в последовательной очереди» — процесс является асинхронной операцией, поэтому конкретный поток не задействован. Возможно, задержка вызвана тем, что потоку пользовательского интерфейса приходится обрабатывать все эти обратные вызовы? Отправляете ли вы сообщения из
SendComplete
обратного вызова или используете несколькоSmtpClient
s и отправляете все сообщения одновременно? Пожалуйста, включите какой-нибудь код в свой вопрос, чтобы мы могли видеть, что происходит на самом деле.3. @VisualVincent, вы сказали, что не задействовано никакого конкретного потока, но я вижу выход многих потоков после отправки электронных писем.
4. @Jimi, если методы SendAsync используют свой внутренний пул потоков, что может вызвать задержку в SendCompletedCallback? Я думаю, что где-то есть ограничение, может быть, там внутренний пул потоков настроен только на один поток, из-за этого я вижу последовательное поведение
5. Как уже было описано, SendMailAsync устанавливает a
TaskCompletionSource
, который передается как методObject
SendAsync . Он также устанавливает пользовательскоеSendCompleted
событие, которое обрабатывает статус ошибки / отмены и вызовы[TaskCompletionSource].TrySetResults()
. Он возвращает задачу. Как вы справляетесь с этими задачами (и как вы их планируете), зависит от вас. Вы можете запустить задачу как threadpool-поток, ожидать выполнения одной задачи илиTask.WhenAll()
списка задач. Где в этом случае выполняются / выполняются задачи, вас не касается, и это не имеет значения.
Ответ №1:
Проблема, я думаю, в том, что SmtpClient устарел:
https://docs.microsoft.com/pt-br/dotnet/api/system.net.mail.smtpclient?view=netframework-4.7.2
«SmtpClient не поддерживает многие современные протоколы. Это только для совместимости. Он отлично подходит для одноразовых электронных писем из инструментов, но не масштабируется до современных требований протокола «.
«Используйте MailKit или другие библиотеки».