ASP.NET C#线程中止异常?
-
11-10-2019 - |
题
我正在尝试建立一个发送电子邮件的小型电子邮件工作者。电子邮件工作者以自己的线程运行。 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();
它不能被抓住,当您应用程序结束时会发生。
更好的实现是用 可取消 环形。