2011-02-23 152 views
3

有一個ASP.NET 2.0的Web應用程序應該允許發送電子郵件。我有一個立即發送電子郵件的Windows服務。我的Web應用程序根據某個模板編寫電子郵件並將其放入MSMQ中,服務從此處獲取。ASP.NET後臺工作線程

問題是,編寫來自模板的消息可能需要一些時間,並且我不希望用戶在構建消息並將其傳遞給服務時等待。

我想了解一些後臺進程,它將監聽通知請求的內部隊列。如果隊列爲空,則該進程什麼都不做,但一旦出現消息,它就開始處理消息。我想只有一個進程不要創建大量線程。

目前我的想法是編寫任務調度程序,它將包含通知請求的隊列。當新項目被添加到隊列中時,調度器檢查發送通知的過程是否正在運行。如果是,那麼它只是將請求添加到隊列中。否則,它會創建一個新的線程,讀取隊列直到它爲空並執行通知請求。

我的問題是我需要確保我的線程不會在ASP.NET完成對客戶端的響應之後死掉,因爲它是我的線程的父線程。問題是做這件事的最好方法是什麼(或者可以做到這一點)?

P.S.如果IIS由於用戶不活動而回收ASP.NET進程,我的線程就會死掉。

回答

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 
+0

ASP.NET返回響應並終止處理響應的進程後,此線程是否會死機? – lostaman 2011-02-23 16:56:04

+0

@lostaman - 它將存活,線程屬於對象,objet位於緩存中。所以它會一直活着,直到緩存死亡,這幾乎是一個應用程序池/ iis重置。 – Peter 2011-02-23 17:40:54

+0

但是這個線程如何連接到緩存? – lostaman 2011-02-23 18:08:55

1

網站和當前發送電子郵件的Windows服務之間的中介服務如何?該站點可以將接收到的原始數據放入新服務的隊列中,新服務將其拾取並編寫消息,並將其放入發送電子郵件的Windows服務的隊列中。這樣,對網站和郵件服務的影響就很小,您只需向流中添加另一個隊列即可。

您正在追求的想法是,所有不需要需要的數據處理都應該從現場網站卸載到後臺服務(或任意數量的後臺服務)中。該網站不是業務邏輯,它只是用戶與幕後邏輯引擎進行交互的用戶界面,其中服務是其中的一部分。所有網站或網站的任何部分需要做的是堅持數據並回到用戶請求的響應。

+1

我同意最好的方法是將數據移動到單獨的服務,但我不能在我的情況下做到這一點,因爲模板機制必須與站點對象進行交互。因此我需要在ASP.NET中運行此過程。 – lostaman 2011-02-23 16:32:37

+1

@lostaman:聽起來像是一些重構工作。各種應用程序上下文(站點,服務等)都應該訪問核心業務功能,它們都不應該保留它。快速修復可能只是從服務項目中引用站點項目,以訪問其內部類和成員,但這是一個馬虎的方法。你一定想把業務邏輯從UI中拉出來。 – David 2011-02-24 10:56:05

+0

我完全同意你的看法。在我的情況下,我需要生成電子郵件消息並將其顯示給用戶。使用服務方法,我需要將數據傳遞給服務並從中獲取準備好的消息。 – lostaman 2011-02-24 22:39:01

0

您可以創建一個Web服務,您可以在其中從ASP.NET應用程序進行異步調用。異步調用將允許您在不阻塞主線程的情況下進行調用。我認爲你可以做一個方法調用,不必等待線程完成。