mvc ActionResult & ajax post & Session 合在一起就出現 奇怪問題....

這次是寫 "處理進度表" 遇到個奇怪問題
又是找了老半天 終於找到了

有個server 後端程式 需處理大量資料
雖然 可以 在前端 跑出 處理中.....
但是真的很久......
所以 "處理進度表" 是無法避免的 解決方案

我的解決方式是:
用  setInterval("Ckconnect()", 1000);
啟動一個 ajax
 function Ckconnect() {
            $.post("/Main/Ajax_DT", {})
                .done(function (Rdata) {
                    var dta = Rdata.DT_STR.split('-');// replace('-',",");
                    var time = dta[0] + "/" + dta[1] + "/" + dta[2] + " " + dta[3] + ":" + dta[4] + ":" + dta[5];
                    $("#ckdt").text(time + ":" + Rdata.proValue);
                    $('#WaitP').progressbar('setValue', Rdata.proValue);
                });
        }
1秒去看一下 Rdata.proValue  處理進度值
而處理的話 也是 post 一個 資料回後端
$.post("/Main/Ajax_Wdata", {....})
後端就
while(...)
{
   變更  Rdata.proValue; 值 讓前台知道
}
******************************************
一開始測都正常 ....
整個專案就在今天寫完測試時
突然發現 進度值 不動了  測試時間也不動了
確定是 "/Main/Ajax_DT" 沒回應
等 "/Main/Ajax_Wdata" 處理完後 時間才動
怎麼會變這樣....
***********************
用新的專案測試後
一個是隔 1秒用 $.post("/Main/Ajax_DT", {}) 去server 要時間
一個是故意 卡死一個 後端
        public ActionResult Begin_Test()//卡死測試
        {
            while (true)
            {
                Pub_param.proValue++;
                Thread.Sleep(1000);
                if (Pub_param.Max_data == 100)
                    break;
            }
            return Json("OK");
        }
是正常的
當 Begin_Test() 跑起來後
$.post("/Main/Ajax_DT", {}) 還是有正常回應
*****************************************
但是正式專案上就是 不回應了
經測試是 $.post("/Main/Ajax_DT", {}) 
一定要等 Begin_Test() 有 return 回到前台
Ajax_DT才會回來
一次只能回來一個就對了
****************************
但測試卻是可以的
這就非常奇怪了..........
經過不斷 交叉拆解 測試
一開始懷疑是 後端卡死 執行緒...但不是
是不是 jquery  $.post 放置的地方或參數問題.....也不是
是 EasyUI 跟  $.post  卡住嗎?.....也不是
*******************************
就這樣....不斷不斷 試驗
終於在一個想都想不到的地方 抓到問題
就是 使用了  Session
   public ActionResult CK_Tname(string Tname)
        {
            SData_SQL Mysd = new SData_SQL();
            int Rcount = Mysd.Ck_Tname(Tname);
            if (Rcount == 0)
               Session["Tname"] = Tname;
            return Json(Rcount);
        }
*********************************
 Session["Tname"] = Tname;

拿掉 就 正常(應該是 Action 不會排隊回來)
用 ViewData試 是OK
用 TempData 也是死 畢竟他也是  Session
********************************************
我猜應該是 Session 是公用變數 
MVC 變成一次只能用一個 Action 去處理 怕2個同時會鎖死吧?我猜
********************************************
總之問題算是找到了
只要一用到 Session ,後面不管是否有再用到 都會變成這種狀況
一般應用應該是不會碰到這種問題
這次是我想用 "進度表" 特殊用法才會用到這問題
*****************************************************
知道後 找到的資料 早看到 就不用查這麼久

但要小心 畢竟一些資料是存在 user端 容易被竄改 有時還會被擋
所以如不是非要用到 需要 2個 ajax 同時回應訊息且cookie資料不重要我才用

一般非必要我覺得我還是會用 Session
畢竟是安全 好處理 ,不用擔心用戶端封鎖cookie
記憶體問題? 能用錢解決的問題就不是問題
用戶同時連線都多到讓server 負擔不了的這種程度...還擔心錢?
+CPU+RAM+SSD ....這都比 資料安全性問題 簡單太多了
而且操作時點一下等一下(不要太久)是還好...

不用Session 不用 Cookies
但是還是要暫存資料做 Action之間 傳遞資料
我是想到一方法解決..
自己利用 session ID 做標記
寫一套 類似存放server端的cookie 來解決 傳遞問題
工程有點浩大還要做測試驗證
真碰到有需要再說
***************************************
另一種解決方案
是看到

在 ASP.NET MVC 中使用非同步控制器

AsyncController 類別
這是另一種問題 我也沒碰過
有人實做過

非同步AsyncController + 網頁截圖 實作教學

這方法並不能解決 我的問題
因為它是將 運行部分 丟到另一個執行緒去做 不占用web server
但還是要等他回來
所以他分2部分
public void 我的執行程式Async
public ActionResult 我的執行程式Completed

前端 ajax 還是 call  "我的執行程式"
還是等 我的執行程式Async 跑完 才會從 Completed return 回來
所以沒有解決這卡住問題
******************************
但這啟發我另一個想法 當還沒找到是Session 卡住時
就是 收到 Ajax 資料就丟給另一個 執行緒 跑,然後return 回來
射後不理..
讓另一個 Ajax 間隔1秒去 check 執行狀況
反正前方用 進度表擋住所有操作 等 執行緒通知 結束
再下一步就可以
這我有實做過類似的功能 但倒不是為了解決這問題
是為了解決 管控 多人同時處理資料庫 的問題用.
最後沒實作 是因 沒找到原因 心理總是毛毛的
畢竟應該是可以的 怎麼就突然卡死?
找不到 會不會 其他地方 死得更慘?
還好有找到
**********************
最後還是用了各人暫存表 來取代 session
使用方式
不能用 Session.SessionID;
Session.SessionID 要一致
就得啟用 Session
Session["id"] =Session.SessionID;
沒啟用 每次都會不同 ID

 public class _Ag_Param
    {
     public string _SID;//使用者 id 紀錄就好 等登出時 再清掉
     public double proValue = 0;
     public string Dstr = "";
    }
    public class Pub_param//公用固定變數
    {
        public static List<_Ag_Param> Ag_Parm = new List<_Ag_Param>();
    }
使用時用ID在 Pub_param.Ag_Parm.Add 加一個 ,
然後用 FIND 找 登出時記的移除 就好.



































留言

熱門文章