2013-02-25 79 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