ASP.NET C # поток прервал исключение? - PullRequest
2 голосов
/ 17 декабря 2010

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

Это исключение:

Начало нового раунда по электронной почте рабочий для петли
Ложусь спать в почтовый работник for-loop
Первый шанс исключение типа 'System.Threading.ThreadAbortException' произошло в mscorlib.dll
Исключение типа 'System.Threading.ThreadAbortException' произошло в mscorlib.dll, но не было обрабатывается в коде пользователя

Это код для EmailWorker

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;
}

Ответы [ 5 ]

3 голосов
/ 16 марта 2011

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

1 голос
/ 17 декабря 2010

Поток, который вы создаете, прерывается asp.net.Создание длительных потоков - главное нет-нет в asp.net.

A у нас есть рабочий обходной путь, которым мы не гордимся ... Создайте таймер для обработки ожидающих сообщений.

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 электронных писем, чтобы тик таймера заканчивался, а новый поднимался ...

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

1 голос
/ 17 декабря 2010

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

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

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

Я не уверен, какой был ваш точный вопрос, но, надеюсь, я ответил на него.

0 голосов
/ 17 декабря 2010

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

 EmailWorkerThread.Abort();

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

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

0 голосов
/ 17 декабря 2010

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

...