Вопрос

Я пытаюсь построить небольшого почтового работника, который отправляет мои электронные письма. Работник электронной почты работает в собственной ветке. Global.asax запускает нить, а затем работает за один раунд, прежде чем бросить это исключение. Я пытался выяснить, куда он его бросает, но, кажется, каждый раз это отличается. Записи напечатаны в текстовый файл, так что это работает, может быть, функции распоряжения?

Это исключение, брошенное:

Запуск нового раунда в работнике электронной почты для петли
Засыпая в почтовом работнике для петли
Первое шанс исключение типа «System.Threading.ThreadAbortException» произошло в mscorlib.dll
Исключение типа «System.Threading.ThreadAbortException» произошло в mscorlib.dll, но не обрабатывался в коде пользователя

Это код для почтового работника

public static class EmailWorker
{
    public static void Work()
    {
        TimeSpan sleepTime = new TimeSpan(0, 1, 0);

        for (; ; )
        {
            Debug.WriteLine("Starting a new round in the email worker for-loop");
            try
            {
                // Get the records
                CS_Code.UtopiaDataContext db = new CS_Code.UtopiaDataContext(); 
                List<CS_Code.Global_Email> emailsToSend = (from xx in db.Global_Emails select xx).ToList();


                // Write the records to a file (for now)
                TextWriter writer = new StreamWriter(@"test.txt", true); // For debugging
                foreach (var email in emailsToSend)
                    writer.WriteLine("To: " + email.Email_Address + ", Subject: " + email.Subject + ", uid:" + email.UserName.ToString());
                writer.Close();
                writer.Dispose();

                // Delete the used records from the database
                foreach (var email in emailsToSend)
                    db.Global_Emails.DeleteOnSubmit(email);
                db.SubmitChanges();
                db.Dispose();


                Debug.WriteLine("Going to sleep in the email worker for-loop");
                Thread.Sleep(sleepTime); // Sleep for 1 minute.
                Debug.WriteLine("Just woke up in the email worker for-loop");
            }
            catch (Exception e)
            {               
                Debug.WriteLine(e.Message);
                break;
            }
        }
    }
}

Это файл Global.asax, который запускает все:

private static Thread EmailWorkerThread { get; set; }

void Application_Start(object sender, EventArgs e)
{
    // Email worker thread
    if ((EmailWorkerThread == null) || (!EmailWorkerThread.IsAlive))
    {
        ThreadStart ts = new ThreadStart(EmailWorker.Work);
        EmailWorkerThread = new Thread(ts);
        EmailWorkerThread.Start();
    }
}

void Application_End(object sender, EventArgs e)
{
    // Email worker thread
    if ((EmailWorkerThread != null) || (EmailWorkerThread.IsAlive))
        EmailWorkerThread.Abort();
    EmailWorkerThread = null;
}
Это было полезно?

Решение

Поток, который вы создаете, прерывается ASP.NET. Создание длинных запущенных потоков является основным нет-нет в ASP.NET.

У нас есть рабочий обходной путь, которым мы не гордимся ... Создайте таймер, который обрабатывает электронные письма.

static Timer processTimer; // declare static at service level

// At the static constructor:
processTimer = new Timer(new TimerCallback(TimerTick), 60000, 10000, defaultInterval); //wait a minute before begin (dueTime = 60000)

Чтобы быть очень осторожным, на мероприятии Timer_tick обрабатывайте максимум n электронных писем, так что тик таймер заканчивается, а новый поднимается ...

Это работает над нашей производственной средой ...

Другие советы

Вам нужно вывести электронную почту из ASP.NET в службу Windows. Вы можете общаться между своей веб -страницей и службой через WCF. ASP.NET не предназначен для длительных задач.

А ThreadAbortException происходит при выключении вашего приложения, и вы звоните EmailWorkerThread.Abort(). Анкет Это ожидаемое поведение, и оно происходит в случайных местах, потому что код может быть в разных «пятнах», когда Application_End вызовы Abort() на ветке.

Согласно MSDN, ThreadAbortException это особое исключение, которое всегда пересматривается даже после обработки вашего кода. Он предназначен для того, чтобы вы знали, что нить закрывается, чтобы дать вам возможность очистить.

Вы, вероятно, выключаете, потому что IIS закрывает рабочую процесс после установленного количества простоя или какого -либо другого наложенного ограничения. Опять же, этого следует ожидать, приложения ASP.NET, как правило, имеют «ограниченные срок службы», так что такие длительные темы, как это, на самом деле не очень хорошая идея.

Я не уверен, что это за вопрос, но, надеюсь, я ответил на него.

Детская нить может жить только до тех пор, пока родительская нить жива. Несмотря на то, что у вас есть поток, определенный в том, что кажется уровнем приложения, я не могу представить, что этот поток на самом деле выживает за пределами потока httprequest. Для меня это означает, что в тот момент, когда ваш поток запроса завершается, ваш ребенок по электронной почте завершается. Поскольку поток спит, следующая строка пытается выполнить, но она не может, потому что поток httprequest уже запустил свой курс.

ThreadAbortException Как следует из названия, бросается, когда работа работает и прерывается. Это происходит в этом месте:

 EmailWorkerThread.Abort();

Это не может быть пойман, и это происходит, когда вы заканчиваются применением.

Лучшей реализацией было бы заменить бесконечную петлю на отмену петля.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top