3

我正在寻找一种使用带有 c# 的 webforms 在 web 中显示“进度条”的方法。

我做了一个简单的例子,我只想要一个标签显示 1%、2%、3% 等关于将在服务器中运行的后台进程。当它完成更新,比如显示警报之类的东西时,真正的需要比这要复杂一些,但我认为我可以自己做。我在代码中遇到的问题是我总是得到 0.. 在我的“进度条”中它没有得到更新,我遗漏了一些东西,但我不知道它是什么。

编辑

我试图每秒提醒该值以查看该值而不是标签,但它无论如何都不起作用。

我错过了OnClientClick="javascript:GetProgress();"第一个问题,我更新了它,它仍然无法正常工作

编辑 2

HttpConext.Current 在将其作为线程调用时为空。我应该使用比会话或应用程序更多的东西,也许是单调类?

任何帮助将非常感激。


来自 ASPX 和 JS 的重要信息

 <div style="width: 800px" class="css_container">
        <cc1:ToolkitScriptManager ID="sm" runat="server" EnableScriptGlobalization="true"
            EnableScriptLocalization="true" AsyncPostBackTimeout="60000" EnablePageMethods="true">
        </cc1:ToolkitScriptManager>
        <asp:UpdatePanel ID="upPanel" runat="server">
            <ContentTemplate>
               <asp:Button ID="btn" runat="server"  Text="Do Something"
                                    CausesValidation="False" OnClick="btn_Click" OnClientClick="javascript:GetProgress();" />
            </ContentTemplate>
        </asp:UpdatePanel>
  </div>

  function GetProgress() {
       PageMethods.GetProcessed(function(result) {
                alert(result);
                if (result < 100) {
                    setTimeout(function(){GetProgress();}, 1000);
                }                  
            });

    }

代码背后的重要事情

[WebMethod(EnableSession=true), ScriptMethod]
    public  static string GetProcessed()
    {
        return HttpContext.Current.Session["processed"].ToString();
    }

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
             Session["processed"] = 0;
        }
    }

protected void btn_Click(object sender, EventArgs e)
    {
       AClass oClass = new AClass();
        Thread oThread = new Thread(delegate()
            {
                oClass.UpdateSession();
            });
           oThread.Start();
    }

来自 Aclass 的重要事项

public class AClass
{ 
    public void UpdateSession()
    {
          for(int i = 0; i< 100; i++)
          {

            HttpContext.Current.Session["processed"] =  i;
            System.Threading.Thread.Sleep(1000);
          }
    }
}
4

4 回答 4

2

我认为这里可能发生了一些事情:

  1. 您的线程可能会在响应结束时终止。我认为您可以通过更改定义线程的方式来解决此问题:

    Thread oThread = new Thread(new ThreadStart(oClass.UpdateSession));
    oThread.IsBackground = true; // Set this
    oThread.Start();
    
  2. 您将字符串百分比返回给回调函数,然后将其与数字进行比较。这不是一个真正的问题,但为了良好的编程,您应该更改您的服务器端GetProcessed()以返回一个实际的整数:

    public static int GetProcessed()
    {
        int result = 0;
        int.TryParse(HttpContext.Current.Session["processed"].ToString()), out result);
        return result;
    }
    
  3. UpdatePanel 请求在后台启动整个页面生命周期。您能否验证此代码不会在您的 GetProcessed() Web 方法的每个滴答声中都重置您的进度?

    if (!IsPostBack)
    {
         Session["processed"] = 0;
    }
    
于 2012-09-27T15:52:34.533 回答
2

问题是您调用的Session不是正在更新值的那个。所以,你有几个选择。

Application首先,如果您的应用程序仅由一个用户使用(不太可能,但我对应用程序一无所知),您可以将其设为变量。

其次,您可以使用某种相关键,以便您可以从Application键控变量中获取值。

在按钮单击中进行更改:

protected void btn_Click(object sender, EventArgs e) 
{
    // NEW CODE
    // set the hidden field value here with a correlation key
    var correlationKey = Guid.NewGuid().ToString();
    this.correlationKey.Value = correlationKey;

    AClass oClass = new AClass(); 
    Thread oThread = new Thread(delegate() 
        { 
            oClass.UpdateSession(correlationKey); 
        }); 
    oThread.Start(); 
}

现在像这样修改 JavaScript:

function GetProgress() {
    PageMethods.GetProcessed(document.getElementById("correlationKey").value,
        function(result) {
            alert(result);
            if (result < 100) {
                setTimeout(function(){GetProgress();}, 1000);
            }   
        });   
}

现在修改GetProcessed方法如下:

[WebMethod(EnableSession=true), ScriptMethod]
public  static string GetProcessed(string correlationKey)
{
    var dictionary = Application["ProcessedQueue"] as Dictionary<string, int>;
    if (dictionary == null || !dictionary.ContainsKey(correlationKey)) { return "0"; }
    return dictionary[correlationKey].ToString();
}

现在修改UpdateSession方法如下:

public void UpdateSession(string correlationKey)
{
    var dictionary = Application["ProcessedQueue"] as Dictionary<string, int>;
    if (dictionary == null)
    {
        dictionary = new Dictionary<string, int>();
        Application["ProcessedQueue"] = dictionary;
    }

    if (!dictionary.ContainsKey(correlationKey)) { dictionary.Add(correlationKey, 0); }

    for (int i = 0; i< 100; i++)
    {
        dictionary[correlationKey] =  i;
        System.Threading.Thread.Sleep(1000);
    }
}

现在清理Page_Load.

于 2012-09-27T15:59:40.967 回答
2

我使用了@Mike 的想法.. 并对其进行了一些更改,因为 HttpContext.Current 为空...并将其替换为静态对象。这对我来说很好,也做了一些并发测试并且工作正常..

<div style="width: 800px" class="css_container">
        <cc1:ToolkitScriptManager ID="sm" runat="server" EnableScriptGlobalization="true"
            EnableScriptLocalization="true" AsyncPostBackTimeout="60000" EnablePageMethods="true">
        </cc1:ToolkitScriptManager>
        <asp:UpdatePanel ID="upPanel" runat="server">
            <ContentTemplate>
               <asp:HiddenField ID="correlationKey" runat="server" />
               <asp:Button ID="btn" runat="server"  Text="Do Something"
                                    CausesValidation="False" OnClick="btn_Click" OnClientClick="javascript:GetProgress();" />
            </ContentTemplate>
        </asp:UpdatePanel>
  </div>

function GetProgress() {
    PageMethods.GetProcessed(document.getElementById("correlationKey").value,
        function(result) {
            alert(result);
            if (result < 100) {
                setTimeout(function(){GetProgress();}, 1000);
            }   
        });   
}

protected void btn_Click(object sender, EventArgs e) 
{
    // NEW CODE
    // set the hidden field value here with a correlation key
    var correlationKey = Guid.NewGuid().ToString();
    this.correlationKey.Value = correlationKey;

    AClass oClass = new AClass(); 
    Thread oThread = new Thread(delegate() 
        { 
            oClass.UpdateSession(correlationKey); 
        }); 
    oThread.Start(); 
}

public class AClass
{
    public static Dictionary<string, int> ProcessedQueue { get; set; }

    public void UpdateSession(string correlationKey)
    {
        var dictionary = ProcessedQueue; // HttpContext.Current.Application["ProcessedQueue"] as Dictionary<string, int>;
        if (dictionary == null)
        {
           dictionary = new Dictionary<string, int>();
           ProcessedQueue = dictionary;// HttpContext.Current.Application["ProcessedQueue"] = dictionary;
        }

        if (!dictionary.ContainsKey(correlationKey)) { dictionary.Add(correlationKey, 0); }

        for (int i = 0; i < 100; i++)
        {
             dictionary[correlationKey] = i;
         System.Threading.Thread.Sleep(1000);
        }
    }
}

[WebMethod(EnableSession = true), ScriptMethod]
public static string GetProcessed(string correlationKey)
{
     var dictionary = AClass.ProcessedQueue; //     HttpContext.Current.Application["ProcessedQueue"] as Dictionary<string, int>;
     if (dictionary == null || !dictionary.ContainsKey(correlationKey)) { return "0"; }
     return dictionary[correlationKey].ToString();
}
于 2012-09-27T17:30:25.753 回答
1

也许我错过了一些东西,但是您的 javascript(至少您在问题中提出的内容)没有更新页面上的任何内容。你说你的进度条一直都是0,这可能是因为你注释掉了改变显示的行。

//document.getElementById("divProgress").innerHTML = result + "%";

显示的值是否alert正确?另外,您是否确认它UpdateSession()运行正确并实际在会话中设置了一个值?

于 2012-09-27T15:43:47.230 回答