UpdatePanel与Session和ViewState的奇怪行为

3

早上好,

这是一个更多关于WTF是什么类型的问题。我的应用程序正在使用ViewState。我在应用程序中放置了一个UpdatePanel,仅用于测试目的。它每秒钟都会访问我的日志表,并为我生成实时日志控制台,以便我查看应用程序如何处理事情。

今天早上,我决定将我的使用ViewState改为Session。现在,我的UpdatePanel不再同步运行,并且“暂停”直到操作完成以更新UpdatePanel/Console。

切换回ViewState可以使事情正常运行...

此外,我的UpdatePanel调用的函数与ViewState或SessionState没有关系,并且没有调用任何一个...

我已经能够在小型测试样本中复现此行为:

TestUpdatePanelWithSession.Master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="TestUpdatePanelWithSession.master.cs" Inherits="Tester2._0.TestUpdatePanelWithSession1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:Timer ID="Timer1" runat="server" Enabled="True" Interval="1000"></asp:Timer>
        <div>
            <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
            </asp:ContentPlaceHolder>
        </div>
        <asp:UpdatePanel ID="UpdatePanel1"
            UpdateMode="Always"
            runat="server">
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
            </Triggers>
            <ContentTemplate>

                <%= System.DateTime.Now.ToString("mm:ss") %>

                    </div>
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>
</body>
</html>

TestUpdatePanelWithSession.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/TestUpdatePanelWithSession.Master" AutoEventWireup="true" CodeBehind="TestUpdatePanelWithSession.aspx.cs" Inherits="Tester2._0.TestUpdatePanelWithSession" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <asp:Label ID="lblTest" runat="server" Text="Label"></asp:Label>
    <asp:Button ID="btnStartTest" runat="server" Text="Test" OnClick="btnStartTest_Click" />
</asp:Content>

TestUpdatePanelWithSession.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Tester2._0
{
    public partial class TestUpdatePanelWithSession : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                Session["SomeIndex"] = 50000;
            }
        }

        protected void btnStartTest_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 1000000; i++)
            {
                System.Threading.Thread.Sleep(500);
                Session["SomeOtherIndex"] = i;

                lblTest.Text = ((int)Session["SomeIndex"] + (int)Session["SomeOtherIndex"]).ToString();
            }
        }
    }
}

如果您将所有的Session更改为ViewState,则上述代码可以正常工作。这是怎么回事?

提前感谢您的课程...


我真的不确定在这里要展示什么代码。它涉及到我的整个应用程序。当我从使用ViewState切换到使用Sessions来存储各种对象时,行为开始出现。肯定有一些解释可以解释UpdatePanel在进行此切换时的行为(不查看代码)?或者也许它应该像使用ViewState一样正常工作,那么我将尝试确定导致UpdatePanel出现此问题的区域。 - Nugs
我可以向您保证,在UpdatePanel中使用Session不会改变其行为,我在使用ASP .net时广泛使用它。 - Gusman
正确,我不想将整个页面放在UpdatePanel中,只想在母版页底部放置一个小型控制台窗口。 - Nugs
那么这就是正确的行为,问题描述不太清楚...在updatepanel之外的任何内容都会导致完整的POST并且执行将暂停直到响应,Session可能会引入一些延迟,没错,但不会锁定updatepanel上的任何内容。 - Gusman
此外,在您的示例中,您可以完全移除会话(Session),睡眠(sleep)会创建延迟,因此Session不会对其产生影响,请测试。 - Gusman
显示剩余16条评论
1个回答

4
测试示例后,问题明显来自于会话的读写锁。在 Page_Load 中删除会话使用可以避免这种行为,但这有点奇怪,因为当 updatepanel 调用页面时,代码并没有被触发。即使将代码移动到其他函数中,在另一个线程中调用它或使用任务也无法阻止这种行为。似乎 ASP .net 分析代码时,当存在使用会话的代码时,即使它没有被执行,它也会阻止会话,从而阻止回调的正常执行。只在控件事件上留下会话操作似乎可以正常工作。根据我的测试,唯一的解决方案是删除 Page_Load 中的会话操作,在某些情况下可能是不可避免的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接