在我面向公众的网络服务器上执行 IISRESET 后,我的应用程序的初始化似乎是正确的。也就是说,在 Application_Start 事件中,我启动了一个新的“电子邮件”线程,其目的是休眠到配置的时间,在“唤醒”时生成一个报告并将其通过电子邮件发送给我的管理用户并返回休眠状态直到配置持续时间过后,将再次创建报告并通过电子邮件发送出去。我目前配置为从 1900 开始,每 12 小时生成一份新报告。
然而,随着时间的推移,这个生产站点会导致创建一个“额外的”线程。反过来,这会导致通过电子邮件发送重复的报告。虽然问题足够温和,但如果可能的话,我想清理它。这是一个片段:
Public Class [Global]
Inherits System.Web.HttpApplication
Public emth As New EmailThread
Private vcomputer As String
Private eventsource As String
Private message1 As String
Public MyInstanceStart As New ThreadStart(AddressOf emth.workerThread)
Public InstanceCaller As New Thread(MyInstanceStart)
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
vcomputer = System.Environment.MachineName
InstanceCaller.Name = "EMAILBOT"
InstanceCaller.Start()
UIF.WriteToLog("Application_Start: EMAILBOT instance Started")
End Sub
检查网络服务器上的应用程序事件日志,我可以在 IISRESET 上正确看到上述消息。随后是workerThread中的另一个“正确”记录事件,它告诉我们代码在下一次报告时间之前将休眠多长时间。这是workerThread的一个片段:
Public Class EmailThread
Public Sub workerThread()
Dim TimeToStart As Date
Dim TimeToStart_Next As Date
Try
Dim Start As Integer = CInt(ConfigurationManager.AppSettings("EmailStartTime"))
Dim iSleep As Integer = CInt(ConfigurationManager.AppSettings("RobotIntervalHours"))
If Start < 1 Or Start > 23 Then Start = 12
If iSleep < 1 Or iSleep > 24 Then iSleep = 12
TimeToStart = New Date(Now.Year, Now.Month, Now.Day, Start, 0, 0)
Do Until TimeToStart > Now
'We missed the start time by some amount...
' compute new time to start by adding RobotIntervalHours
TimeToStart = DateAdd(DateInterval.Hour, iSleep, TimeToStart)
Loop
TimeToStart_Next = DateAdd(DateInterval.Hour, iSleep, TimeToStart)
' 'Set NEXT TimeToStart for reporting
' Compute how long to wait now
Dim SleepMinutes As Long
While 1 = 1
SleepMinutes = System.Math.Abs(DateDiff(DateInterval.Minute, Now, TimeToStart))
strScheduledStart = FormatDateTime(TimeToStart, DateFormat.GeneralDate)
UIF.WriteToLog("EmailThread will sleep for " & CStr(SleepMinutes) & " minutes; " & _
"waking at next starttime: " & strScheduledStart)
Thread.CurrentThread.Sleep(TimeSpan.FromMinutes(SleepMinutes))
'---------------------------------------------------------------------------------------
' Upon waking, resume here:
'---------------------------------------------------------------------------------------
TimeToStart = TimeToStart_Next
TimeToStart_Next = DateAdd(DateInterval.Hour, iSleep, TimeToStart)
BC.NextRobotStartTime = FormatDateTime(TimeToStart, DateFormat.GeneralDate)
StartRobotProcess(strScheduledStart) 'Robot reports generated
SleepMinutes = 0
End While
Catch ex As Exception
UIF.LogException(ex, "CRITICAL: Exception in 'EmailThread.workerThread' has been logged:", 100)
End Try
End Sub
上面的代码似乎工作正常(就像我说的,在 IISRESET 之后,我看到 Application_Start 事件中记录的一个事件,然后是我的“电子邮件”线程中的日志条目:“EmailThread 将休眠 nnn 分钟......等等。 “。但不知何故(随着时间的推移)我得到了另一个 EmailThread 实例,因此在预定的“唤醒时间”生成了 2 个报告,而不仅仅是一个报告。
在分配给该网站的 IIS 应用程序池中,我有以下设置:
- Recycle worker processes (in minutes) is UNCHECKED
- Recycle worker process (number of requests) is UNCHECKED
- Recycle worker process (at various times) is UNCHECKED / nothing specified
- [Idle timeout] Shutdown worker process after being idle for (time in minutes) is UNCHECKED
我注意到可以再次输入 Application_Start 事件(在第一次之后大约 38 分钟),这会导致我的代码再次运行并创建另一个 [和不需要的] 线程。
我将不胜感激有关如何收紧这一点以使这种症状消失的建议。