首先,不推薦在ASP.NET后臺中,啟動Long-Running的任務。因為無論是用的Task還是ThreadPool.QueueUserWorkItem,ASP.NET不會知道它們在后臺運行,這會產生一些問題,比如:
創(chuàng)新互聯(lián)專注于企業(yè)營銷型網站建設、網站重做改版、海鹽網站定制設計、自適應品牌網站建設、H5技術、電子商務商城網站建設、集團公司官網建設、外貿營銷網站建設、高端網站制作、響應式網頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為海鹽等各大城市提供網站開發(fā)制作服務。
當修改web.config的時候,會觸發(fā)Appdomain被回收(盡管此時IIS web服務器進程w3wp.exe仍然活著),IIS本身也會每29小時回收應用程序池,這都會導致后臺線程被終止,從而引發(fā)異常。
當ASP.NET要回收AppDomain,它會讓已經存在的請求處理完再回收,ASP.NET和IIS服務器也知道這些請求正在運行,所以等它們完成。問題是ASP.NET不知道任何后臺線程比如一個計時器或者其他,它只知道和request相關的操作。
事實上,在后臺長時間的運行某些任務實在不是web server該做的事情,通常都可以用其他的方式來避免這樣做,比如:
用console application和windows任務管理器,或者使用Windows服務等。
但是,如果確定要這樣做,那么在ASP.NET中也有些辦法保證后臺任務能夠安全的退出。
方法一,使用IRegisteredObject接口。
通過IRegisteredObject接口,并且調用HostingEnvironment.RegisterObject方法在ASP.NET中注冊它。
當Appdomain要被回收的時候,會調用已注冊對象中的IRegisteredObject中的Stop方法。
public interface IRegisteredObject { void Stop(bool immediate); }
已注冊對象沒有被取消注冊(即沒有調用HostingEnvironment.UnregisterObject方法來取消注冊),那么Stop方法會被調用兩次,第一次調用的時候,immediate參數(shù)為false,此時如果已注冊對象已經停止了,那么應該調用 HostingEnvironment.UnregisterObject方法來取消注冊。如果還不取消注冊,那么30秒后,該方法會被再次執(zhí)行(這是最后的機會),不同的是此時傳入的immediate參數(shù)為true,此時注冊對象必須先調用 UnregisterObject 方法然后返回;否則應用程序管理器將移除該對象的注冊。
使用IRegisteredObject接口并不是用來處理后臺Long-Running任務的,但是這個功能可以讓你安全的退出后臺任務。
舉個例子,如下:
public class JobHost : IRegisteredObject { private readonly object _lock = new object(); private bool _shuttingDown; public JobHost() { HostingEnvironment.RegisterObject(this); } public void Stop(bool immediate) { lock (_lock) { _shuttingDown = true; } HostingEnvironment.UnregisterObject(this); } public void DoWork(Action work) { lock (_lock) { if (_shuttingDown) { return; } work(); } } }
如上面的代碼,ASP.NET要回收Appdomain時,Stop 方法會被調用,這個方法會獲得一個鎖,在DoWork方法也獲得同樣的所,這樣的話,DoWork在運行的時候,Stop方法不得不等待。
方法二,使用HostingEnvironment.QueueBackgroundWorkItem
HostingEnvironment.QueueBackgroundWorkItem 方法在.NET4.5.2中引入,QueueBackgroundWorkItem (QBWI) 通過ASP.NET運行時,注冊后臺任務。這樣的話,由于ASP.NET知道有后臺任務,他就不會立即回收Appdomain,當然,這不意味著后臺任務可以做任何事情。當ASP.NET需要做回收的時候,它可以通過一個CancellationToken通知后臺任務,并且等待30s讓工作完成。如果30秒內沒問出,那么這個工作也會消失了。關于QueueBackgroundWorkItem的更多細節(jié),可以通過
http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx學習。
方法二,使用HangFire
HangFire是一個開源的類庫,提供簡單的方法在ASP.NET中執(zhí)行后臺Long-Running任務。這個類庫需要一些額外的存儲上的支持,SQLServer,redis或者MSMQ。HangFire的資料在http://hangfire.io/
參考資料
http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/
http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html
http://blogs.msdn.com/b/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx
名稱欄目:ASP.NET的后臺Long-Running任務
網站路徑:http://chinadenli.net/article30/gisoso.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供微信公眾號、靜態(tài)網站、商城網站、電子商務、面包屑導航、網頁設計公司
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)