1. 程式人生 > >WEB耗時任務的處理方案

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();

}

            好啦,大體過程就是這樣了,歡迎大家指正,也歡迎討論其他處理長耗時任務的可具體實施的思路。