首先,不推薦在ASP.NET后臺中,啟動Long-Running的任務。因為無論是用的Task還是ThreadPool.QueueUserWorkItem,ASP.NET不會知道它們在后臺運行,這會產(chǎn)生一些問題,比如:

創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、海鹽網(wǎng)站定制設(shè)計、自適應品牌網(wǎng)站建設(shè)、H5技術(shù)、電子商務商城網(wǎng)站建設(shè)、集團公司官網(wǎng)建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應式網(wǎng)頁設(shè)計等建站業(yè)務,價格優(yōu)惠性價比高,為海鹽等各大城市提供網(wǎng)站開發(fā)制作服務。
當修改web.config的時候,會觸發(fā)Appdomain被回收(盡管此時IIS web服務器進程w3wp.exe仍然活著),IIS本身也會每29小時回收應用程序池,這都會導致后臺線程被終止,從而引發(fā)異常。
當ASP.NET要回收AppDomain,它會讓已經(jīng)存在的請求處理完再回收,ASP.NET和IIS服務器也知道這些請求正在運行,所以等它們完成。問題是ASP.NET不知道任何后臺線程比如一個計時器或者其他,它只知道和request相關(guān)的操作。
事實上,在后臺長時間的運行某些任務實在不是web server該做的事情,通常都可以用其他的方式來避免這樣做,比如:
用console application和windows任務管理器,或者使用Windows服務等。
但是,如果確定要這樣做,那么在ASP.NET中也有些辦法保證后臺任務能夠安全的退出。
方法一,使用IRegisteredObject接口。
通過IRegisteredObject接口,并且調(diào)用HostingEnvironment.RegisterObject方法在ASP.NET中注冊它。
當Appdomain要被回收的時候,會調(diào)用已注冊對象中的IRegisteredObject中的Stop方法。
public interface IRegisteredObject { void Stop(bool immediate); }已注冊對象沒有被取消注冊(即沒有調(diào)用HostingEnvironment.UnregisterObject方法來取消注冊),那么Stop方法會被調(diào)用兩次,第一次調(diào)用的時候,immediate參數(shù)為false,此時如果已注冊對象已經(jīng)停止了,那么應該調(diào)用 HostingEnvironment.UnregisterObject方法來取消注冊。如果還不取消注冊,那么30秒后,該方法會被再次執(zhí)行(這是最后的機會),不同的是此時傳入的immediate參數(shù)為true,此時注冊對象必須先調(diào)用 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 方法會被調(diào)用,這個方法會獲得一個鎖,在DoWork方法也獲得同樣的所,這樣的話,DoWork在運行的時候,Stop方法不得不等待。
方法二,使用HostingEnvironment.QueueBackgroundWorkItem
HostingEnvironment.QueueBackgroundWorkItem 方法在.NET4.5.2中引入,QueueBackgroundWorkItem (QBWI) 通過ASP.NET運行時,注冊后臺任務。這樣的話,由于ASP.NET知道有后臺任務,他就不會立即回收Appdomain,當然,這不意味著后臺任務可以做任何事情。當ASP.NET需要做回收的時候,它可以通過一個CancellationToken通知后臺任務,并且等待30s讓工作完成。如果30秒內(nèi)沒問出,那么這個工作也會消失了。關(guān)于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任務
網(wǎng)站路徑:http://www.chinadenli.net/article30/gisoso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號、靜態(tài)網(wǎng)站、商城網(wǎng)站、電子商務、面包屑導航、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)