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

发布于 2024-10-06 16:38:39 字数 3877 浏览 8 评论 0原文

在我的面向公众的网络服务器上进行 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 分钟),这会导致我的代码再次运行并创建另一个[和不需要的]线程,

我将不胜感激 。如何加强这一点以使这种症状消失。

After an IISRESET on my public facing webserver, the initialization of my app seems correct. That is, in the Application_Start event I launch a new "email" thread whose purpose is to sleep until the configured time, upon "waking" produce a report and email it to my administrative user(s) and go back to sleep until the configured duration elapses at which time, the report is created again and emailed out. I am currently configured to start at 1900 and produce a new report every 12 hours.

As time marches on with this production site, however, something is causing an "extra" thread to be created. This, in turn, results in a duplicate report being emailed. While the problem is benign enough, I'd like to clean this up if possible. Here's a snippet:

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

Examining the Application Event Log on the webserver, I can see the above message properly upon an IISRESET. This is followed by another "proper" logged event in the workerThread which tells us how long the code will sleep before the next report time. Here is a snippet from the 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

The above code seems to work fine (like I stated, after an IISRESET, I see the one logged event from the Application_Start event followed by the log entry from my "email" thread: "EmailThread will sleep for nnn minutes...etc.". But somehow (over time) I am getting another instance of the EmailThread thus producing 2 reports instead of just one at the scheduled "wake time".

In the IIS application pool assigned to this website, I have the following settings:

- 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

I have noticed that the Application_Start event can be entered again (in one case roughly 38 minutes after the first time) which causes my code to run again and create another [and unwanted] thread.

I would appreciate suggestions on how to tighten this up to make this symptom go away.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傻比既视感 2024-10-13 16:38:39

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

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

What I can think of is that in your application in IIS, you have an extra application (converting virtual folder to Application) in one of the subfolders of your website.

ASP.NET performance counters can also help you with the number of applications and threads created. Use perfmon to monitor them.

假装爱人 2024-10-13 16:38:39

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

Doesn't figure out why, but it would be easy to check a flag in the application object, check it during startup and, if set, return.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文