ASP.NET C#线程中止异常?

时间:2010-12-17 14:49:47

标签: c# asp.net multithreading global-asax threadabortexception

我正在尝试建立一个发送电子邮件的小型电子邮件工作者。电子邮件工作者在自己的线程中运行。 global.asax启动线程,然后在抛出此异常之前运行一轮。我一直试图找出它抛出的地方,但每次似乎都不同。记录打印到文本文件,以便工作,也许处置功能?

这是抛出的异常:

  

在电子邮件中开始新一轮   工人for-loop
  去睡觉吧   电子邮件工作者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 个答案:

答案 0 :(得分:3)

您需要将EmailWorker移出ASP.NET并进入Windows服务。您可以通过WCF在您的网页和服务之间进行通信。 ASP.NET不适用于长时间运行的任务。

答案 1 :(得分:1)

当您的应用程序关闭并且您致电ThreadAbortException时,会发生EmailWorkerThread.Abort()。这是预期的行为,它发生在随机位置,因为当Application_End调用线程上的Abort()时,代码可能位于不同的“点”。

根据MSDNThreadAbortException是一个特殊的异常,即使在您的代码处理之后也始终重新抛出。它旨在让您知道线程正在关闭以便为您提供清理的机会。

您的应用程序可能正在关闭,因为IIS在一定量的空闲时间或其他强加的限制之后关闭了工作进程。同样,这是可以预料的,ASP.NET应用程序往往具有“有限的生命周期”,因此像这样长时间运行的线程并不是一个好主意。

我不确定你的确切问题是什么,但希望我能回答。

答案 2 :(得分:1)

您正在创建的线程正在被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封电子邮件,因此计时器滴答结束,新的计时器上升......

这正在我们的生产环境......

答案 3 :(得分:0)

只要父线程处于活动状态,子线程就可以生存。即使你已经在应用程序级别定义了一个线程,我也无法想象这个线程实际上存在于HttpRequest线程之外。对我而言,这意味着您的请求线程终止的那一刻,您的孩子EmailWorkerThread终止。由于线程处于休眠状态,下一行会尝试执行,但它不能,因为HttpRequest线程已经运行了。

答案 4 :(得分:0)

顾名思义,

ThreadAbortException在线程工作并被中止时抛出。这发生在这个地方:

 EmailWorkerThread.Abort();

当应用程序结束时,它无法捕获并发生。

更好的实现方法是用cancelable循环替换无限循环。