ASP.NET 后台工作线程

3
我有一个ASP.NET 2.0 Web应用程序,应该允许发送电子邮件。我有一个Windows服务,可以立即发送电子邮件。我的Web应用程序根据一些模板组成电子邮件消息,并将其放入MSMQ中,服务从那里获取它。
问题在于,从模板中组成消息可能需要一些时间,我不希望用户在消息被组成并传递给服务时等待。
我考虑了一些后台进程,它将监听通知请求的内部队列。如果队列为空,则进程不执行任何操作,但是一旦消息出现,它就开始处理消息。我希望只有一个进程,以免创建大量线程。
目前,我的想法是编写任务计划程序,其中包含通知请求队列。当新项目添加到队列中时,调度程序会检查是否正在运行发送通知的进程。如果是,则仅将请求添加到队列中。否则,它会创建新线程,该线程将读取队列直到其为空并执行通知请求。
我的担忧是,我需要确保我的线程不会在ASP.NET完成响应客户端后死亡,因为它是我的线程的父线程。问题是什么是最佳方法来做到这一点(或者是否可能这样做)?
附言:如果IIS由于用户不活动而回收ASP.NET进程,则我的线程死亡是可以的。
3个回答

1

那么,在站点和当前发送电子邮件的 Windows 服务之间增加一个中介服务如何?站点可以将其接收到的原始数据放入新服务的队列中,新服务会提取它并组成消息,然后将其放入用于发送电子邮件的 Windows 服务的队列中。这样,对站点和邮件服务的影响最小,您只是在流程中添加了另一个队列。

您正在推动的想法是,所有不需要实时处理的数据处理都应该从实时站点转移到后台服务(或任意数量的后台服务)。站点不是业务逻辑,它只是用户与幕后逻辑引擎交互的UI,其中服务是其中的一部分。站点或站点的任何部分需要做的就是持久化数据并继续响应用户请求。


1
我认为最好的方法是将数据移动到单独的服务中,但在我的情况下,模板机制必须与站点对象交互,因此我需要在ASP.NET内运行此过程。 - lostaman
1
@lostaman:听起来需要进行一些重构。各种应用上下文(站点、服务等)都应该访问核心业务功能,而不是独占它们。一个快速的解决方法可能只是从服务项目中引用站点项目,以便访问其内部类和成员,但这是一种粗糙的方法。你肯定想把业务逻辑从UI中分离出来。 - David
我完全同意你的观点。在我的情况下,我需要生成电子邮件消息并将其显示给用户。使用服务方法,我需要将数据传递到服务中,并从中获取准备好的消息。 - lostaman

1
我使用以下类作为基类。我从这个类继承并在其中放置我的逻辑。然后,我将该类的实例存储在ASP.Net缓存中,以便保留引用并始终可以找到它。对于您的目的,在从此类继承后,在ExecuteProcess内创建一个无限循环"while(true)",然后在循环的顶部/底部放置延迟"thread.sleep(500)"或类似的东西。每次循环都检查队列中的消息。
Imports System.Threading

Public MustInherit Class LongRunningProcess
    Public ReadOnly Property Running() As Boolean
        Get
            Return _Running
        End Get
    End Property

    Public ReadOnly Property Success() As Boolean
        Get
            Return _Success
        End Get
    End Property

    Public ReadOnly Property Exception() As Exception
        Get
            Return _Exception
        End Get
    End Property

    Public ReadOnly Property StartTime() As DateTime
        Get
            Return _StartTime
        End Get
    End Property

    Public ReadOnly Property EndTime() As DateTime
        Get
            Return _EndTime
        End Get
    End Property

    Public ReadOnly Property Args() As Object
        Get
            Return _Args
        End Get
    End Property


    Protected _Running As Boolean = False
    Protected _Success As Boolean = False
    Protected _Exception As Exception = Nothing
    Protected _StartTime As DateTime = DateTime.MinValue
    Protected _EndTime As DateTime = DateTime.MinValue
    Protected _Args() As Object = Nothing
    Protected WithEvents _Thread As Thread

    Private _locker As New Object()

    Public Sub Execute(ByVal Arguments As Object)
        SyncLock (_locker)
            'if the process is not running, then...'
            If Not _Running Then
                'Set running to true'
                _Running = True
                'Set start time to now'
                _StartTime = DateTime.Now
                'set arguments'
                _Args = Arguments
                'Prepare to process in a new thread'
                _Thread = New Thread(New ThreadStart(AddressOf ExecuteProcess))

                'Start the thread'
                _Thread.Start()
            End If
        End SyncLock
    End Sub

    Protected MustOverride Sub ExecuteProcess()
End Class

ASP.NET返回响应并终止处理响应的进程后,这个线程会死掉吗? - lostaman
@lostaman - 它会存活的,线程属于对象,而对象在缓存中。因此,它将一直存在,直到缓存死亡,这几乎等同于应用程序池/IIS重置。 - Peter
@lostaman - HttpContext.Current.Cache("SomeKey") = myobject,其中myobject是从LongRunningProcess继承的对象实例。 - Peter

0
你可以创建一个Web服务,在ASP.NET应用程序中进行异步调用。异步调用将允许您在没有阻塞主线程的情况下进行调用。我认为您可以进行单向调用,而无需等待线程完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接