ASP.NET后台工作者线程

时间:2011-02-23 16:01:43

标签: asp.net concurrency

有一个ASP.NET 2.0 Web应用程序,应该允许发送电子邮件。我有一个Windows服务,可以立即发送电子邮件。我的Web应用程序根据某个模板编写电子邮件消息并将其放在MSMQ中,服务从那里获取。

问题是从模板编写消息可能需要一些时间,我不希望用户在编写消息并将其传递给服务时等待。

我想一些会监听通知请求内部队列的后台进程。如果队列为空,则进程不执行任何操作,但只要消息出现,它就会开始处理消息。我想只有一个进程来不创建很多线程。

目前我的想法是编写任务调度程序,它将包含通知请求队列。将新项目添加到队列时,调度程序会检查发送通知的进程是否正在运行。如果是,那么它只是将请求添加到队列中。否则,它会创建新线程,该线程将读取队列,直到它为空并执行通知请求。

我担心的是我需要确保我的线程在ASP.NET完成对客户端的响应后不会死,因为它是我的线程的父线程。问题是最好的方法是什么(或者可以做到这一点)?

P.S。如果由于用户不活动而导致IIS回收ASP.NET进程,我的线程就会死掉。

3 个答案:

答案 0 :(得分:1)

网站与当前发送电子邮件的Windows服务之间的中间服务如何?该站点可以将收到的原始数据丢弃到新服务的队列中,新服务将其拾取并编写消息,然后将其放入发送电子邮件的Windows服务的队列中。这样,对网站和邮件服务的影响很小,您只需在流中添加另一个队列。

您正在努力的想法是,所有不需要生效的数据处理应该从实际站点卸载到后台服务(或任意数量的后台服务) )。该站点不是业务逻辑,它只是用户与幕后逻辑引擎交互的UI,其中服务是其中的一部分。站点或站点的任何部分需要做的就是保留数据并返回响应用户请求。

答案 1 :(得分:1)

我使用下面的类作为基类。我从这个类继承并将我的逻辑放在其中。然后,我将此类的实例存储在ASP.Net缓存中,以便保留引用,并且我总能找到它。为了你的目的,在继承ExecuteProcess中的这个类之后创建一个无限的while循环“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

答案 2 :(得分:0)

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