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

这是一个例外:

在电子邮件工作者往返中开始新的回合
要在电子邮件工作者的循环中睡觉
MSCORLIB.DLL中发生的第一个机会“系统。
MSCORLIB.DLL中发生的“ System.ThreadBortException”类型的例外

这是电子邮件工作者的代码

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中创建长期运行的线程是主要的禁忌。

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封电子邮件处理,因此计时器的结尾,一个新的电子邮件升起...

这在我们的生产环境中工作...

其他提示

您需要将电子邮件工作者移出ASP.NET并进入Windows服务。您可以通过WCF在网页和服务之间进行通信。 ASP.NET并不是针对长期运行的任务。

ThreadAbortException 当您的应用程序关闭并致电时发生 EmailWorkerThread.Abort(). 。这是预期的行为,它发生在随机位置,因为当代码可以在 Application_End 呼叫 Abort() 在线程上。

按照 MSDN, , 这 ThreadAbortException 是一个特殊的例外,即使在被您的代码处理后,它也总是会复发。它旨在让您知道该线程正在关闭,以使您有机会清理。

您的申请可能会关闭,因为IIS在固定的闲置时间或其他施加的限制之后关闭了工作流程。同样,这是可以预料的,ASP.NET应用程序往往具有“有限的寿命”,因此像这样的长期跑步线程并不是一个好主意。

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

只要父螺纹还活着,子线程才能生存。即使您在似乎是应用程序级别的线程中定义了一个线程,我也无法想象该线程实际上在HTTPREQUEST线程之外生存。对我来说,这意味着,当您的请求线程终止时,您的孩子emailworkerThread终止了。由于线程正在睡觉,因此下一行尝试执行,但不能因为HTTPREQUEST线程已经运行其课程。

ThreadAbortException 顾名思义,当线程工作并流产时,会抛出。这发生在这个地方:

 EmailWorkerThread.Abort();

它不能被抓住,当您应用程序结束时会发生。

更好的实现是用 可取消 环形。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top