2013-08-03 39 views
3

我是MVC的新手,所以如果我遺漏了任何東西,請原諒我。在MVC線程中存儲Session中的值

在我的控制器之一,我開始一個類,做了一些處理,並輸出這樣的字符串:

[HttpPost] 
public ActionResult Check(string reg) 
{ 
    string sCarmodel; 
    GetRegInfo gri = new GetRegInfo(reg, out sCarmodel); 
    Session["test"] = sCarmodel; 

    return View("Check"); 
} 

到目前爲止好,和sCarmodel的輸出被正確地存儲在會話那裏可以稍後在視圖中訪問。但是,我需要將該類放在單獨的線程中,因爲它需要一些時間來完成它,並且我想返回View aschyncronosly。所以,我想這一點:

[HttpPost] 
public ActionResult Check(string reg) 
{ 
    var getreginfoThread = new Thread(
     () => 
     { 
      string sCarmodel; 
      GetRegInfo gri = new GetRegInfo(reg, out sCarmodel); 
      Session["test"] = sCarmodel; 
     } 
     ); 

    getreginfoThread.Start(); 

    return View("Check"); 
} 

我知道我可以「sCarmodel」的值在數據庫中的類的內部存儲,但我一直在尋找一種方式使用數據庫跳過。使用線程時,sCarmodel的值不會存儲在Session中,並且稍後當我試圖檢索Session時,會話爲null

任何人都可以提供一些建議,關於如何在線程中訪問類中的值?

謝謝!

編輯: 問題解決了,感謝大家對他們的建議!

回答

0

我已經通過在TempData中存儲類的實例解決了我的問題。此外,而不是線程,我使用任務更好。這裏是我的解決方案:

[HttpPost] 
     public ActionResult GetRegInfo(string reg) 
     { 
      var gri = new GetRegInfo(reg); 
      TempData["GetRegInfo"] = gri; 

      Action<object> action = (object obj) => gri.Start(); 
      var t1 = new Task(action, "GetRegInfo"); 
      t1.Start(); 

      return View("bilforsakring"); 
     } 

後來我用Ajax的一個JavaScript計時器並獲得這樣的值:

[OutputCache(NoStore = true, Duration = 0)] 
     public ActionResult GetRegInfoAjax() 
     { 
      if (TempData["GetRegInfo"] != null) 
      { 
       var g = (GetRegInfo)TempData["GetRegInfo"]; 
       return Content(g.sCarmodel); 
      } 
      else 
      { 
       return Content("null"); 
      } 
     } 
0

這不是該值沒有存儲在會話中。它是。問題是,您的代碼將繼續與您創建的線程並行執行,並且在訪問 Session["test"]時,它尚未由您的線程分配。 你必須以某種方式重新組織你的代碼。此外,它不推薦在asp.net應用程序中啓動線程,因爲它非常耗費資源。

編輯

看來,它確實犯規設置會話變量。如果你真的想這樣做,這樣,你就可以使用CallContext爲:

CallContext.LogicalSetData("CurrentSession", Session); 

var getreginfoThread = new Thread(
    () => 
    { 
     string sCarmodel; 
     GetRegInfo gri = new GetRegInfo(reg, out sCarmodel); 
     var session = (HttpSessionState)CallContext.LogicalGetData("CurrentSession"); 

     session["test"] = sCarmodel; 
    } 
    ); 

getreginfoThread.Start(); 

return View("Check"); 

你會以某種方式等待這個數據不爲空,然後把它用Session["test"]

+0

那麼,我正在使用計時器每5秒檢查一次Session [「test」]。它始終爲空,即使後臺線程完成。 – Dimo

+0

對不起,但它不適合我。 CallContext.LogicalGetData(「test」)始終爲空:/ – Dimo

+0

對不起,請參閱我的編輯。 – ghord

1

您需要以某種方式將會話傳遞給後臺線程。例如,請參閱here

順便說一下,你爲什麼不使用Task Parallel Library

+0

Task Pararell Library與我正在使用的方法相比有什麼進步? – Dimo

+1

您將使用線程池,它更適合於並行運行的短任務。您可以在沒有TPL的情況下使用線程池,但爲什麼不在切換到現代API時? – zmbq

+0

你能否提供一個示例代碼? – Dimo

0

HttpContext會話對象的父/所有者對象不會傳輸到新線程,因此您的會話不能在主線程以外的線程中訪問。

我建議你使用async/await從你的線程中返回sCarmodel,並將它設置爲主線程中的Session。

3

在處理請求期間將自定義對象放入會話中。

將對此自定義對象的引用傳遞給後臺線程。

在後臺線程中設置自定義對象的屬性。

確保你做了任何必要的同步。

+0

適合我。簡單而優雅!不知道線程安全性,但它是一個簡單的解決方案,並且在嘗試了各種不同的東西之後終於可以工作:) –

0

我建議你不要在線程中使用Session對象,因爲它不是線程安全的。在ASP.NET中,每個請求都有自己的線程和自己的會話。

你永遠描述一個現實的問題(很遺憾),所以我真的不知道你想什麼來解決,但手動旋轉了一個新的線程,並把數據會話不是一個解決辦法呢。

如果你想要做的事情異步讓Web服務器服務於其他客戶,而這樣做的背景是什麼,然後在異步控制器看起來也許是: http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4

再次,這將是非常有用的知道什麼是它試圖達到建議一個適當的解決方案。

+0

我通過在TempData中存儲類的引用來解決我的問題。似乎很好地工作。 – Dimo

0

不過,我需要把這個類在一個單獨的線程,因爲它需要一些時間來完成它,我想返回視圖aschyncronosly。

錯誤。這完全是錯誤的方式來解決這個問題。在ASP.NET應用程序中,除非已經將該工作保存到持久性存儲中,否則當有更多工作要做時,不應該返回。保留內存中的工作(即使用線程或任務)是不正確的解決方案。

正確的解決方案是使用持久性存儲(例如,Azure隊列,MSMQ或WebSphere MQ)來存儲要完成的工作,然後擁有一個單獨的服務來讀取該隊列,採取適當的操作並存儲導致另一個持久的數據結構。然後,客戶端可以輪詢(例如,HTTP請求)「結果」數據結構和/或當結果被保存時通知客戶端(例如,SignalR)。

我進入更多的細節on my blog,也有一些示例代碼使用那裏,如果你是絕對確定你想採取不安全的路線。

+0

談論做出假設。這個過程需要3-4秒鐘,它只返回一個字符串。你認爲我會爲這樣的事情經歷所有的麻煩嗎?大聲笑... – Dimo

+0

你讀過我的博客文章嗎?還是菲爾·哈克連接的那個談論它有多危險?我們在這裏討論語義的正確性。如果你不在乎做得對,那麼只需做簡單的事情並在返回結果之前完成處理。 –

相關問題