在构造函数中请求了另外三个服务,并且初始化了SmtpClient(这是MailKit中的)
public MailQueueManager( IMailQueueProvider provider, IOptions<EmailOptions> options, ILogger<MailQueueManager> logger) { _options = options.Value; _client = new SmtpClient { // For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS) ServerCertificateValidationCallback = (s, c, h, e) => true }; // Note: since we don't have an OAuth2 token, disable // the XOAUTH2 authentication mechanism. if (_options.DisableOAuth) { _client.AuthenticationMechanisms.Remove("XOAUTH2"); } _provider = provider; _logger = logger; }启动队列时创建了新的线程,并且将线程句柄保存起来:
public void Run() { if (_isRunning || (_thread != null && _thread.IsAlive)) { _logger.LogWarning("已经运行,又被启动了,新线程启动已经取消"); return; } _isRunning = true; _thread = new Thread(StartSendMail) { Name = "PmpEmailQueue", IsBackground = true, }; _logger.LogInformation("线程即将启动"); _thread.Start(); _logger.LogInformation("线程已经启动,线程Id是:{0}", _thread.ManagedThreadId); }线程启动时运行了方法StartSendMail:
private void StartSendMail() { var sw = new Stopwatch(); try { while (true) { if (_tryStop) { break; } if (_provider.IsEmpty) { _logger.LogTrace("队列是空,开始睡眠"); Thread.Sleep(_options.SleepInterval); continue; } if (_provider.TryDequeue(out MailBox box)) { _logger.LogInformation("开始发送邮件 标题:{0},收件人 {1}", box.Subject, box.To.First()); sw.Restart(); SendMail(box); sw.Stop(); _logger.LogInformation("发送邮件结束标题:{0},收件人 {1},耗时{2}", box.Subject, box.To.First(), sw.Elapsed.TotalSeconds); } } } catch (Exception ex) { _logger.LogError(ex, "循环中出错,线程即将结束"); _isRunning = false; } _logger.LogInformation("邮件发送线程即将停止,人为跳出循环,没有异常发生"); _tryStop = false; _isRunning = false; }这个方法不断的从队列读取邮件并发送,当 遇到异常,或者_tryStop为true时跳出循环,此时线程结束,注意我们会让线程睡眠,在适当的时候。