WEB耗時任務的處理方案
最近有一個需求,從網頁上傳一個文字包到後臺處理,處理時長可能在幾分鐘到幾十分鐘。原來的方案就是直接接收一個ajax請求處理資料,然後返回。遇到的問題是:經過十幾分鐘的處理後,後臺返回結果到前端,前端收不到該結果了。我想應該是http連線超時了,除非長連線,沒有哪個請求可以這樣無限制地等待。於是著手改進方案,先說一下思路:
1.前端上傳檔案到後臺後,後臺開啟一個子執行緒處理耗時任務,主執行緒直接返回結果給前端,當前請求結束,無須等待子任務的處理結果。注意這裡的返回結果只是表示檔案上傳成功,是一個階段性的結果而已。
2.前端開啟一個輪詢,每隔一秒查一下當前任務的處理進度,直到任務處理結束。
回答一下這個思路中的幾個關鍵點
1.輪詢檢查的依據是什麼?後臺根據什麼來知道當前是誰在查詢?答案:Session.對Session不太瞭解的同學可以再做一下功課,這裡不展開。
2.主執行緒和新開的子執行緒之間是需要交換資料的,包括子執行緒和查詢執行緒之間也是需要交換資料的,這個交換資料是用什麼來實現?答案:HttpRuntime Cache,對這個不熟悉的也做一下功課,這裡簡單理解為就是一塊可以共享資料的記憶體區域。
好了,思路和關鍵點都解決了,這裡再來貼一下關鍵點的程式碼,讓大家有一個更清晰的認識
1.開啟子執行緒
//sessionid是作為一個引數傳到子執行緒裡面去的,我們儲存資料到cache中是以sessionid+關鍵字的形式來做key值,而session值是不能在子執行緒中直接獲取的,所以傳進去
String sessionId = Session.SessionID;
ThreadProc threadProc = new ThreadProc(sessionId);
Thread thread = new Thread(new ThreadStart(threadProc.process));
thread.IsBackground = true;
thread.Start();
子執行緒類:
class ThreadProc{
private string sessionId = "";
public ThreadProc(string sessionId){
this.sessionId = sessionId;
}
public void process(){
//這裡具體處理耗時任務
//儲存結果
cache.WriteCache<Result>(result,sessionId+"result");
}
}
2.cache的存取
Cache cache = new Cache();
//讀取
Result result = cache.GetCache<Result>(sessionId+"result");
//儲存
cache.WriteCache<Result>(result,sessionId+"result");
這裡Cache類是對原始HttpRuntime Cache的一次封裝,示例如下
public class Cache{
private static System.Web.Caching.Cache cache = HttpRuntime.Cache;
public T GetCache<T>(string cacheKey) where T:class{
if(cache[cacheKey] != null){
return (T)cache[cacheKey];
}
return default(T);
}
public void WriteCache<T>(T value,string cacheKey) where T:class{
cache.Insert(cacheKey,value,null,DateTime.Now.AddMinute(10),System.Web.Caching.Cache.NoSlidingExpiration);
}
}
3.輪詢處理
public string CheckProcState(){
string sessionId = Session.SessionID;
Cache cache = new Cache();
Result result = cache.GetCache<Result>(sessionId+"result");
return result.ToJson();
}
好啦,大體過程就是這樣了,歡迎大家指正,也歡迎討論其他處理長耗時任務的可具體實施的思路。