如何最好地调试ASP.NET Web应用程序中不需要的线程的创建

时间:2010-12-07 22:34:34

标签: asp.net multithreading event-log application-start address-operator

在面向公众的网络服务器上的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

检查Web服务器上的应用程序事件日志,我可以在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事件的一个记录事件,然后是来自我的“email”线程的日志条目:“EmailThread将睡眠nnn分钟.. .etc。“。但不知何故(随着时间的推移)我正在获得另一个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分钟后的一个案例中),这会导致我的代码再次运行并创建另一个[和不需要的]线程。

我很欣赏有关如何加强这种症状以使这种症状消失的建议。

2 个答案:

答案 0 :(得分:1)

我能想到的是,在IIS中的应用程序中,您的网站的一个子文件夹中有一个额外的应用程序(将虚拟文件夹转换为应用程序)。

ASP.NET性能计数器还可以帮助您创建应用程序和线程的数量。使用perfmon来监控它们。

答案 1 :(得分:0)

不明白为什么,但是检查应用程序对象中的标志很容易,在启动时检查它,如果设置,则返回。