Example #1
0
        /// <summary>
        /// 取消异步邮件发送
        /// </summary>
        public void SendAsyncCancel()
        {
            // 因为此类为非线程安全类,所以 SendAsyncCancel 和发送邮件方法中操作MessageQueue部分的代码肯定是串行化的。
            // 所以不存在一边入队,一边出队导致无法完全取消所有邮件发送

            // 1、清空队列。
            // 2、取消正在异步发送的mail。
            // 3、设置计划数量=完成数量
            // 4、执行 AutoDisposeSmtp()

            // 1、清空队列。
            MailUserState tempMailUserState = null;

            while (MessageQueue.TryDequeue(out tempMailUserState))
            {
                Interlocked.Decrement(ref m_messageQueueCount);
                MailMessage message = tempMailUserState.CurMailMessage;
                InnerDisposeMessage(message);
            }
            tempMailUserState = null;
            // 2、取消正在异步发送的mail。
            m_SmtpClient.SendAsyncCancel();
            // 3、设置计划数量=完成数量
            PrepareSendCount = CompletedSendCount;
            // 4、执行 AutoDisposeSmtp()
            AutoDisposeSmtp();
        }
Example #2
0
        /// <summary>
        /// 声明在 SmtpClient.SendAsync() 执行完后释放相关对象的回调方法   最后触发的委托
        /// </summary>
        protected void SendCompleted4Dispose(object sender, AsyncCompletedEventArgs e)
        {
            MailUserState state = e.UserState as MailUserState;

            if (state.CurMailMessage != null)
            {
                MailMessage message = state.CurMailMessage;
                this.InnerDisposeMessage(message);
                state.CurMailMessage = null;
            }

            if (state.IsSmpleMail)
            {
                if (state.AutoReleaseSmtp && state.CurSmtpClient != null)
                {
                    //#if DEBUG
                    //                    Debug.WriteLine("释放SmtpClient");
                    //#endif
                    state.CurSmtpClient.Dispose();
                    state.CurSmtpClient = null;
                }
            }
            else
            {
                if (!e.Cancelled)   // 取消的就不计数
                {
                    CompletedSendCount++;
                }

                if (state.AutoReleaseSmtp)
                {
                    AutoDisposeSmtp();
                }

                // 若批量异步发送,需要设置信号
                //#if DEBUG
                //                Debug.WriteLine("Set" + Thread.CurrentThread.ManagedThreadId);
                //#endif
                AutoResetEvent.Set();
            }

            // 先释放资源,处理错误逻辑
            if (e.Error != null && !state.IsErrorHandle)
            {
                throw e.Error;
            }
        }
Example #3
0
        private void InnerSendMessageSync()
        {
            var msg = CheckSendMail();

            if (msg.Count > 0)
            {
                throw new FormatException(MailInfoHelper.GetMailInfoStr(msg));
            }
            try
            {
                var mMailMessage = CreateMessagex();

                #region 异步发送邮件

                if (PrepareSendCount == 1)
                {
                    // 情况一:不重用 SmtpClient 实例会将PrepareSendCount设置为1
                    // 情况二:计划发送只有一条
                    m_SmtpClient.SendAsync(mMailMessage, AsycUserState);
                    if (m_autoDisposeSmtp)
                    {
                        m_SmtpClient = null;
                    }
                }
                else
                {
                    // 情况一:重用 SmtpClient 逻辑,即我们可以直接操作全局的 m_SmtpClient
                    // 情况二:批量发送邮件 PrepareSendCount>1
                    // 情况三:PrepareSendCount 还未设置,为0。比如场景在循环中做些判断,再决定发邮件,循环完才调用 SetBatchMailCount 设置计划邮件数量

                    MailUserState state = new MailUserState()
                    {
                        AutoReleaseSmtp = m_autoDisposeSmtp,
                        CurMailMessage  = mMailMessage,
                        CurSmtpClient   = m_SmtpClient,
                        UserState       = AsycUserState,
                    };

                    MessageQueue.Enqueue(state);
                    Interlocked.Increment(ref m_messageQueueCount);

                    if (m_SendMailThread == null)
                    {
                        m_SendMailThread = new Thread(() =>
                        {
                            // noItemCount 次获取不到元素,就抛出线程异常
                            int noItemCount = 0;
                            while (true)
                            {
                                if (PrepareSendCount != 0 && PrepareSendCount == CompletedSendCount)
                                {
                                    // 已执行完毕。
                                    this.AutoDisposeSmtp();
                                    break;
                                }
                                else
                                {
                                    MailUserState curUserState = null;

                                    if (!MessageQueue.IsEmpty)
                                    {
                                        //#if DEBUG
                                        //                                            Debug.WriteLine("WaitOne" + Thread.CurrentThread.ManagedThreadId);
                                        //#endif
                                        // 当执行异步取消时,会清空MessageQueue,所以 WaitOne 必须在从MessageQueue中取到元素之前
                                        AutoResetEvent.WaitOne();

                                        if (MessageQueue.TryDequeue(out curUserState))
                                        {
                                            Interlocked.Decrement(ref m_messageQueueCount);
                                            m_SmtpClient.SendAsync(curUserState.CurMailMessage, curUserState);
                                        }
                                    }
                                    else
                                    {
                                        if (noItemCount >= 10)
                                        {
                                            // 没有正确设置 PrepareSendCount 值。导致已没有邮件但此线程出现死循环
                                            this.InnerDisposeSmtp();

                                            throw new Exception(MailValidatorHelper.EMAIL_PREPARESENDCOUNT_NOTSET_ERROR);
                                        }

                                        Thread.Sleep(1000);
                                        noItemCount++;
                                    }
                                }
                                // SmtpClient 为null表示异步预计发送邮件数已经发送完,在 OnSendCompleted 进行了 m_SmtpClient 释放
                                if (m_SmtpClient == null)
                                {
                                    break;
                                }
                            }

                            m_SendMailThread = null;
                        });
                        m_SendMailThread.Start();
                    }
                }

                #endregion 异步发送邮件
            }
            catch (Exception e)
            {
                throw new FormatException(e.Message);
            }
        }
Example #4
0
        /// <summary>
        /// 发送Email
        /// </summary>
        private void InnerSendMessage()
        {
            bool hasError = false;

            var msg = CheckSendMail();

            if (msg.Count > 0)
            {
                throw new FormatException(MailInfoHelper.GetMailInfoStr(msg));
            }
            var mMailMessage = CreateMessagex();

            if (!hasError)
            {
                if (m_IsAsync)
                {
                    #region 异步发送邮件

                    if (PrepareSendCount == 1)
                    {
                        // 情况一:不重用 SmtpClient 实例会将PrepareSendCount设置为1
                        // 情况二:计划发送只有一条

                        // PrepareSendCount 是发送单条邮件。
                        MailUserState state = new MailUserState()
                        {
                            AutoReleaseSmtp = m_autoDisposeSmtp,
                            CurMailMessage  = mMailMessage,
                            CurSmtpClient   = m_SmtpClient,
                            IsSmpleMail     = true,
                            UserState       = AsycUserState,
                        };
                        if (m_autoDisposeSmtp)
                        {
                            // 由发送完成回调函数根据 IsSmpleMail 字段进行释放
                            m_SmtpClient = null;
                        }

                        ThreadPool.QueueUserWorkItem((userState) =>
                        {
                            // 无需 catch 发送异常,因为是异步,所以这里 catch 不到。
                            MailUserState curUserState = userState as MailUserState;
                            curUserState.CurSmtpClient.SendAsync(mMailMessage, userState);
                        }, state);
                    }
                    else
                    {
                        // 情况一:重用 SmtpClient 逻辑,即我们可以直接操作全局的 m_SmtpClient
                        // 情况二:批量发送邮件 PrepareSendCount>1
                        // 情况三:PrepareSendCount 还未设置,为0。比如场景在循环中做些判断,再决定发邮件,循环完才调用 SetBatchMailCount 设置计划邮件数量

                        MailUserState state = new MailUserState()
                        {
                            AutoReleaseSmtp = m_autoDisposeSmtp,
                            CurMailMessage  = mMailMessage,
                            CurSmtpClient   = m_SmtpClient,
                            UserState       = AsycUserState,
                        };

                        MessageQueue.Enqueue(state);
                        Interlocked.Increment(ref m_messageQueueCount);

                        if (m_SendMailThread == null)
                        {
                            m_SendMailThread = new Thread(() =>
                            {
                                // noItemCount 次获取不到元素,就抛出线程异常
                                int noItemCount = 0;
                                while (true)
                                {
                                    if (PrepareSendCount != 0 && PrepareSendCount == CompletedSendCount)
                                    {
                                        // 已执行完毕。
                                        this.AutoDisposeSmtp();
                                        break;
                                    }
                                    else
                                    {
                                        MailUserState curUserState = null;

                                        if (!MessageQueue.IsEmpty)
                                        {
                                            //#if DEBUG
                                            //                                            Debug.WriteLine("WaitOne" + Thread.CurrentThread.ManagedThreadId);
                                            //#endif
                                            // 当执行异步取消时,会清空MessageQueue,所以 WaitOne 必须在从MessageQueue中取到元素之前
                                            AutoResetEvent.WaitOne();

                                            if (MessageQueue.TryDequeue(out curUserState))
                                            {
                                                Interlocked.Decrement(ref m_messageQueueCount);
                                                m_SmtpClient.SendAsync(curUserState.CurMailMessage, curUserState);
                                            }
                                        }
                                        else
                                        {
                                            if (noItemCount >= 10)
                                            {
                                                // 没有正确设置 PrepareSendCount 值。导致已没有邮件但此线程出现死循环
                                                this.InnerDisposeSmtp();

                                                throw new Exception(MailValidatorHelper.EMAIL_PREPARESENDCOUNT_NOTSET_ERROR);
                                            }

                                            Thread.Sleep(1000);
                                            noItemCount++;
                                        }
                                    }
                                    // SmtpClient 为null表示异步预计发送邮件数已经发送完,在 OnSendCompleted 进行了 m_SmtpClient 释放
                                    if (m_SmtpClient == null)
                                    {
                                        break;
                                    }
                                }

                                m_SendMailThread = null;
                            });
                            m_SendMailThread.Start();
                        }
                    }

                    #endregion 异步发送邮件
                }
                else
                {
                    #region  步发送邮件

                    try
                    {
                        m_SmtpClient.Send(mMailMessage);
                        m_CompletedSendCount++;
                    }
                    catch (ObjectDisposedException smtpDisposedEx)
                    {
                        throw smtpDisposedEx;
                    }
                    catch (InvalidOperationException smtpOperationEx)
                    {
                        throw smtpOperationEx;
                    }
                    catch (SmtpFailedRecipientsException smtpFailedRecipientsEx)
                    {
                        throw smtpFailedRecipientsEx;
                    }
                    catch (SmtpException smtpEx)
                    {
                        throw smtpEx;
                    }
                    finally
                    {
                        if (mMailMessage != null)
                        {
                            InnerDisposeMessage(mMailMessage);
                            mMailMessage = null;
                        }
                        AutoDisposeSmtp();
                    }

                    #endregion  步发送邮件
                }
            }
        }