Как SendSync работает с пулом потоков

#vb.net #sendmail #smtpclient

#vb.net #отправка почты #smtpclient

Вопрос:

Вопрос1:

Я отправляю сообщение с помощью SendAsync:

https://docs.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient.sendasync?view=netframework-4.7.2

Я отправляю огромные электронные письма, и я получаю слишком большую задержку в обратном вызове сообщения: 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 . Это ожидаемо. В первом используется a SendOrPostCallback . Считайте это управляемым событиями. Это отличается от того, как вы можете обрабатывать пул этих объектов. Используя этот 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 или другие библиотеки».