2013-02-25 76 views
4

我已經實現了一些工作,它將值添加到線程內的會話狀態。我希望這些值可以在線程之外使用(顯然)。會話模式「ServerState」不能正確處理線程中的會話

當會話狀態模式爲「InProc」時,添加到會話的信息在會話之外可用,沒有任何問題。

然而,當會話狀態模式爲「StateServer」時,行爲是不同的。基本上線程內設置的值是堅持有時有時而不是。這對我來說似乎是隨機的。

這是重現問題的代碼。

public partial class _Default : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
    } 

    protected void store_Click(object sender, EventArgs e) 
    { 
     // Set the session values to default. 
     Session["Test1"] = "No"; 
     Session["Test2"] = "No"; 

     // Set the Test1 session value in the thread. 
     ThreadObject threadObject = new ThreadObject() { Username = Page.User.Identity.Name, SessionState = Session }; 
     worker = new Thread(new ParameterizedThreadStart(Work)); 
     worker.Start(threadObject); 

     // Set the Test2 session value in this thread just to compare. 
     Session["Test2"] = "Yes"; 
    } 

    protected void print_Click(object sender, EventArgs e) 
    { 
     // Print out the Session values. 
     label1.Text = string.Empty; 
     label1.Text += "Inside Thread: " + Session["Test1"] + ", \n"; 
     label1.Text += "Outside: " + Session["Test2"] + "\n"; 
    } 

    private static Thread worker; 

    public static void Work(object threadObject) 
    { 
     // Retrieve the Session object and set the Test2 value. 
     ThreadObject threadObject1 = (ThreadObject)threadObject; 
     HttpSessionState currentSession = threadObject1.SessionState; 
     currentSession["Test1"] = "Yes"; 
    } 
} 

public class ThreadObject 
{ 
    public string Username { get; set; } 
    public HttpSessionState SessionState { get; set; } 
} 

上面的代碼工作正常SessionState的模式= 「InProc方式」,但隨機配備:

<sessionState mode="StateServer" 
    stateConnectionString="tcpip=localhost:42424" 
    cookieless="false" 
    timeout="20"/> 

任何想法?

編輯:所以根據下面的註釋線程需要在請求(主線程)完成之前完成,否則添加到會話的任何東西都會丟失。這是因爲在主線程結束時,會話被序列化併發送到數據存儲(Out of Process或SQL Server)。

回答

1

我認爲這是一個計時問題 - 不能保證您的工作線程在您設置標籤值時執行。它需要幾個MS來創建和啓動步伐。屆時,主線程的其餘部分可能已經完成。您可以通過將調試輸出和查看執行代碼的順序來測試。

如果您需要保證線程中的代碼執行(這消除了對線程的需求) - 您可以使用WaitOne()線程方法讓主線程等待工作線程返回。但是,根據線程中設置的值在並行過程中可用是有風險的。

此外 - 恕我直言,我不會使用ASP.NET應用中的線程 - 我相信共識是​​他們有點危險。由於產生的線程內的錯誤代碼,我看到應用程序池崩潰。

+0

我認爲你對_race condition_是正確的,但是線程對ASP.NET也很重要。如果實施和正確使用,沒有什麼不好的。讓ASP.NET Main-Thread等待任何東西都會使線程可用於處理其他請求 - 這就是MVC允許Task 的原因。 – TGlatzer 2013-02-25 05:45:01

+0

我不能不同意 - 即使您的警告 - 「如果正確實施」似乎是一個常見問題:-) – Ripside 2013-02-25 05:48:26

+0

嘿,標籤設置代碼是按鈕點擊的一部分,我等了超過幾秒鐘之前試圖將會話值輸出到標籤中。 所以我不太確定這是一個計時問題。 重複按下print_Click按鈕應該最終允許線程將其值設置到會話中。 – Ivan 2013-02-25 05:55:23