2010-11-09 96 views
0

我有一個應用程序,其中一個動作觸發了一些電子郵件發送出去。電子郵件的數量是可變的,可以是從10到1,000的任何地方每個動作在後臺發送大量電子郵件 - 創建線程或使用ThreadPool?

我不希望應用程序掛起而郵件正在發送(因此惱人的用戶),並希望在後臺發送它們。

我以前沒有使用線程,所以這就是爲什麼我需要你的幫助。你會手動創建線程嗎?或者這是使用ThreadPool的好例子嗎?我希望這項任務的優先級較低,並儘可能使用最少的資源,因爲即使電子郵件遲了一個小時,我也不介意。

感謝您的幫助
馬爾科

回答

1

這裏如果你`重新使用DB去另一個建議... ,創建與需要發送的消息相關的任務(即創建一個表示要完成的任務的表),並使用Quartz.NET或類似的命令(您也可以創建Windows服務),查找不完整的任務並執行它們(將它們標記爲完成以防它們被成功執行)。

+0

我已經走了類似的東西,但使用Windows任務計劃程序和連接到我的數據庫的控制檯應用程序。你的答案是最接近的,所以我會接受你的答案。 – Marko 2010-11-14 20:51:35

0

所以我的建議是使用線程池。它會允許你排隊所有東西,而不是分別運行它們,使它使用更少的資源,但是當然,處理所有東西需要更長的時間,但正如你所說,時間不是問題。

3

事實上,在ASP.NET中進行線程化並不是一個好主意。當請求結束並回傳給用戶時,Asp.net會處理大量的資源。由於您不希望用戶等待,所以您會遇到這種情況,您認爲可以安全使用的ASP.NET對象真的處置完畢。

您最好的選擇是創建一個外部服務(在IIS中運行的wcf服務或具有公開wcf接口的Windows服務),這些.net頁面可以異步調用,並讓該請求運行直至完成。不用擔心線程等。它運行在它自己的進程中,並在完成時完成。既然你不關心告訴用戶已經完成了,你就不必擔心它傳回了。通過這種方式,如果您需要使用其他某個頁面使用相同的服務界面,則需要調用該界面。在

網頁開始使用WCF:

http://bloggingabout.net/blogs/dennis/archive/2007/04/20/wcf-simple-example.aspx

http://msdn.microsoft.com/en-us/library/bb332338.aspx

http://www.c-sharpcorner.com/Articles/ArticleListing.aspx?SectionID=1&SubSectionID=192

How to start using WCF/WPF?

+0

謝謝@Kevin,絕對聽起來很有希望。對C#4.0的TaskParallel庫有什麼想法?我沒有使用WCF服務,因此我可能需要一些時間來實現您的解決方案。 – Marko 2010-11-09 21:17:32

+0

任務並行庫非常簡潔,但個人而言,如果你不關心完成需要多長時間,我會避免它。在不需要它的項目中引入外部複雜性毫無意義。如果你想消除我提到的線程問題,任務庫不會繞過它。我會找到一些啓動WCF的例子。 – kemiller2002 2010-11-09 21:23:21

+0

您的解決方案似乎是最好的解決方案,但是我缺乏WCF的經驗意味着我不得不花費大量時間來開發它,並可能在最初幾次出錯。然而,解決方案似乎是最好的主意,這意味着我應該購買一本關於WCF的書並開始閱讀。再次感謝@凱文。 – Marko 2010-11-14 20:54:04

0

你可以簡單地使用BackgroundWorker類。

鏈接的MSDN頁面有一個很好的例子,包括進度報告和取消操作的可能性。

編輯:
進展報告和消除可能不適合於Web應用程序,但BackgroundWorker的處理所有的髒東西與你創建一個線程。

EDIT2:
如果你想發送許多並行的郵件,你可以看看的Task Parallel Library

0

您可以使用任務從工作線程產生處理電子郵件。

如果這是錘擊CPU太多,你可以創建一個新的調度程序,減少了併發性:http://msdn.microsoft.com/en-us/library/ee789351.aspx

static void StartMailTasks(string[] addresses) 
{ 
    List<Task> tasks = new List<Task>(); 
    foreach (var address in addresses) 
    { 
     tasks.Add(Task.Factory.StartNew(Email, address)); 
    } 

    Task.Factory.ContinueWhenAll(tasks.ToArray(), AllDone, TaskContinuationOptions.OnlyOnRanToCompletion); 
    Task.Factory.ContinueWhenAny(tasks.ToArray(), ReportError, TaskContinuationOptions.OnlyOnFaulted); 
} 

static void AllDone(Task[] tasks) 
{ 
    // All is well 
} 

static void ReportError(Task errorTask) 
{ 
    // Log or report the error 
} 

static void Email(object state) 
{ 
    // send the e-mail 
    // Can throw error, if needed 
}