4

在我的 page1.aspx 中,我使用线程从数据库生成报告。

//on button click
Hashtable ht = (Hashtable)Session["ReportParam"];
ReportThreadClass rth = new ReportThreadClass(ht);
Thread thread = new System.Threading.ThreadStart(rth .Run);
thread.Start();

在我的线程类的 rum 方法中,我正在更新 Hashtable 中的值,即我创建了多少页。

//in thread' method        
public virtual void Run()
{      
    int pagecount=0;
    while(done)
    {
        //loading data from DB and generating html pages

        ht["Total_Pages"] = pagecount;
    }
}

在我的 Page2.aspx 我正在从会话变量中读取值

Hashtable ht = (Hashtable)Session["ReportParam"];
int TotalPages = (int) ht["Total_Pages"];

当我在 InProc 模式下运行上面的代码时,一切正常,我从会话中获取更新的值。因为每件事都存储在静态变量中,并且 ht 被 Session 引用,所以它会在 session 中自动更新(不需要将 HashTable 重新分配给 session )。

但是当我在状态服务器(OutProc 模式)中运行代码时,它需要通过序列化哈希表将会话数据存储在不同的进程中。

但是即使在 Thread 完全运行之后,Total_Pages 的值也不会在 Page2.aspx 中更新。

那么是否有任何事件或方法被触发以将会话变量中的所有更新存储到 State-Server ,如果是,请告诉我。如果没有,请建议我在 page2.aspx 中获取更新值。

4

3 回答 3

1

我会像这样明确地 SET 和 GET SessionState:

在你的线程运行

// no complex object like hastable, just a plain value...
Session["pageCount"] = pageCount;

在您的 page2.apsx 中:

var pageCount = (int) Session["pageCount"]??0;

您的报告线程在使用进程外会话状态时未更新其会话值的原因是因为会话无法检测哈希表的值已更改,因此它不会使用序列化版本更新底层存储仓促。当您明确存储一个不可变对象时,它将持久化一个它的值已更改;

由于当您的线程完成时会话可能已经消失,所以一个更好的选择是获取对 SqlSessionStateStore 的引用并调用 SetAndReleaseItemExclusive。最终,您可能希望拥有一个可以处理您的场景的重载 SessionStateProvider。

于 2013-06-16T14:44:09.317 回答
0

效率较低,但我可能只是 ping 数据库以获取 Page2 上的页数。

或者为 Page1 上的页数创建一个单独的会话值,同时执行其他所有操作。(编辑:不要介意第二部分,这就是 Rene 下面的建议)。

于 2013-06-18T23:45:21.527 回答
0

In Out Proc Mode Session 在某些事件之后被保存,因此如果您的线程正在更新您的会话变量,那么它将不会保留在存储中。

如果您使用 Inproc 模式,则会话存储在静态字典中,因此如果您的线程对其进行更新,您将获得任何页面的更新值。

因此,对于这种情况,您有两种解决方案

  1. 使用 inProc 模式
  2. 在你的线程类中维护一个字典,键为会话 id,值是你的哈希表,所以如果 page2.aspx 想要读取哈希表的值,那么它会将他的会话 id 传递给方法并返回所需的值。
于 2013-06-19T09:02:30.353 回答