如何在会话存储在状态服务器(Web Garden)中的多线程中使用会话变量

Posted

技术标签:

【中文标题】如何在会话存储在状态服务器(Web Garden)中的多线程中使用会话变量【英文标题】:How to use Session variables with multi threading where session is stored in state server (Web Garden) 【发布时间】:2021-01-14 19:40:49 【问题描述】:

我需要将旧应用程序中的状态管理从 inProc 更改为 StateServer

有在新线程中执行的方法。

代码如下所示。

protected void btnTransaction_Click(object sender, EventArgs e)

    timerTrans.Enabled = true;
    timerTrans.Interval = 200;
    Thread thread = new Thread(new ParameterizedThreadStart(DoAllWork));
    thread.Start(dbConnectionString);


public void DoAllWork(object connectionString)

   DBAccess dba = new DBAccess(connectionString.ToString());
   Session["NextTransactionId"] = dba.getNewTransactionId();

   //Other work

   foreach(transaction t in transactions)
   
       ShowTrasnactionStatus("Processing transaction "+t.id);
   

   //Other work

   Session["FinalStatus"] = "All Transactions Completed";
   Session["TransactionStatus"] = "Done";


private void ShowTrasnactionStatus(string statusMsg)

    Session["TransactionStatus"] = statusMsg;


protected void timerTrans_Tick(object sender, EventArgs e)

    lblStatus.Text = Session["TransactionStatus"].ToString();
    
    if (Session["TransactionStatus"].ToString() == "Done")
    
         //Final Stage of Transaction Processing 
         lblStatus.Text = "Getting final status ...";
         billEndTime = DateTime.Now;

         ShowFinalStatus();
         timerBilling.Enabled = false;
    

启用网络花园后,使用会话变量更新状态不会按预期工作。

我尝试过使用类变量而不是会话变量。 使用缓存而不是会话。

它们都不适合我。

注意:此代码来自至少 8 年前开发的现有应用程序。

我只想在不破坏功能的情况下在网络花园中运行它。

【问题讨论】:

使用那个线程你什么也得不到,web 请求已经在它们自己的线程中执行了。如果您想执行一项长期运行的作业,那在 8 年前也是错误的做法,而且只是偶然地起作用 - IIS 对该线程一无所知,因此只要请求完成,它就可以免费 GC 任何资源。会话可能会在该线程仍在运行时关闭。检查The Dangers of implementing recurring background tasks in ASP.NET 还要检查How to run background tasks in ASP.NET,它显示了长时间运行作业的可用机制。该问题没有显示任何 实际 正在完成的工作,只有一些有风险的控制更新,因此很难推荐一种或另一种技术。也许根本不需要线程?也许您可以使用异步/等待?也许您确实需要一种方法来运行长时间的工作并显式将数据传递给它? 真正的问题是如何报告进度以跟踪长期运行的作业并将其显示给用户?并显示它以响应 ASP.NET 旧更新面板投票?即使没有会话处于活动状态,该作业也会运行,因此使用会话是有风险的。轮询也很昂贵,这就是为什么应用程序使用 SignalR 从客户端向浏览器发送消息的原因。 @PanagiotisKanavos 感谢 cmets。这解释了很多。对于这个应用程序 SingleR 不是一个选项。另外,我不愿意对运行了 8 年的代码做任何大的改动。 那么您唯一的选择就是保持原样,因为如果不进行这些更改,您将无法在网络花园中运行它。 【参考方案1】:

我创建了一个数据库表并将值存储在那里而不是会话变量。在那里我使用了 GUID+KEY 来识别 DB 中的正确值。

我创建了一个方法,当进程完成时删除数据库中的记录,这样可以减少数据库中的搜索成本。

注意:写入 db 并检索它的成本很高。

这可能不是完美的解决方案。但这可以被认为是一种高成本的解决方法。

【讨论】:

以上是关于如何在会话存储在状态服务器(Web Garden)中的多线程中使用会话变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在服务器端 Blazor 中存储会话数据

Cookie 会话身份验证是如何工作的?

探讨Web开发中的Session存储与管理

session的存储方式和配置

Web学习之Session

Web核心之Cookie