/// <summary>
 /// Копировать в новый экземпляр
 /// </summary>
 internal static MailData Copy(MailData mailData)
 {
     return(new MailData(mailData.ticks, mailData.message, mailData.exception));
 }
        private void Execute()
        {
            // --- thread safe
            var key = Key();
            var internalLastSend  = GetLastSendThreadSafe();
            var internalFrequency = GetFrequencyThreadSafe();

            // --------------

            //logger.Log("Сборщик уведомлений. Execute. '{0}', '{1}', '{2}'", key, internalLastSend, internalFrequency);
            Debug.WriteLine("[{0}] {1} Сборщик уведомлений. Execute. '{2}', '{3}', '{4}'", Thread.CurrentThread.ManagedThreadId, key, key, internalLastSend, internalFrequency);

            //Thread.Sleep(new TimeSpan(internalFrequency));
            while (DateTime.Now.Ticks - internalLastSend < internalFrequency)
            {
                Thread.Sleep(10);

                // --- thread safe
                internalLastSend  = GetLastSendThreadSafe();
                internalFrequency = GetFrequencyThreadSafe();
                // --------------
            }

            var             count        = 0;
            List <MailData> mailDataCopy = null;

            // --- thread safe
            cacheLock.EnterUpgradeableReadLock();
            try
            {
                count        = mailDatas.Count();
                mailDataCopy = new List <MailData>(count);
                foreach (var data in mailDatas)
                {
                    mailDataCopy.Add(MailData.Copy(data));
                }
                cacheLock.EnterWriteLock();
                try
                {
                    mailDatas.Clear();
                }
                finally
                {
                    cacheLock.ExitWriteLock();
                }
            }
            finally
            {
                cacheLock.ExitUpgradeableReadLock();
            }
            // --------------

            //logger.Log("Сборщик уведомлений. Execute. Число элементов для отправки '{0}'. Завершение. '{1}'", count, key);
            Debug.WriteLine("[{0}] {1} Сборщик уведомлений. Execute. Число элементов для отправки '{2}'. Завершение. '{3}'", Thread.CurrentThread.ManagedThreadId, key, count, key);
            Console.WriteLine("[{0}] {1} Сборщик уведомлений. Execute. Число элементов для отправки '{2}'. Завершение. '{3}'", Thread.CurrentThread.ManagedThreadId, key, count, key);

            if (mailDataCopy != null && mailDataCopy.Count > 0)
            {
                var sendMail = new SendMail();
                try
                {
                    sendMail.Send(name, nameSpace /*, logger*/, new List <MailData>(mailDataCopy));
                }
                catch (Exception ex)
                {
                    //logger.LogException("Сборщик уведомлений. Execute. Ошибка.", ex);
                    Debug.WriteLine("[{0}] {1} Сборщик уведомлений. Execute. Ошибка. {2}", Thread.CurrentThread.ManagedThreadId, key, ex.Message);

                    // Вернуть копию обратно
                    cacheLock.EnterWriteLock();
                    try
                    {
                        mailDatas.InsertRange(0, mailDataCopy);
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                }
            }
        }