c#中的Web进度条

Posted

技术标签:

【中文标题】c#中的Web进度条【英文标题】:Web Progress Bar in c# 【发布时间】:2012-09-27 15:37:09 【问题描述】:

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

我做了一个简单的例子,我只想要一个标签来显示 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);
          
    

【问题讨论】:

会不会是因为//document.getElementById("divProgress").innerhtml = result + "%";这行被注释掉了? 我试图提醒它,而不是标签.. 我没有张贴标签以免混淆我将从问题中删除它抱歉 您正在从后台线程访问 Session 对象...在 ASP.NET 中这是不好的做法。 这将是一个好习惯吗?有什么建议可以归档我想做的事情吗? 【参考方案1】:

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

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

    Thread oThread = new Thread(new ThreadStart(oClass.UpdateSession));
    oThread.IsBackground = true; // Set this
    oThread.Start();
    

    您正在向回调函数返回一个字符串百分比,然后将其与一个数字进行比较。这不是一个真正的问题,但为了良好的编程,您应该更改您的服务器端 GetProcessed() 以返回一个实际的整数:

    public static int GetProcessed()
    
        int result = 0;
        int.TryParse(HttpContext.Current.Session["processed"].ToString()), out result);
        return result;
    
    

    UpdatePanel 请求在后台启动整个页面生命周期。您能否验证此代码不会在您的 GetProcessed() Web 方法的每个滴答声中都重置您的进度?

    if (!IsPostBack)
    
         Session["processed"] = 0;
    
    

【讨论】:

啊,是的,我敢打赌UpdatePanel 仍然在做着可怕的魔法,即使他使用 javascript 来访问服务器。我想知道 #3 是否需要检查。 也许在 ViewState 而不是会话中使用它来解决并发问题? 你知道,我认为什么时候是线程,会话丢失.. HttpContext.Current 【参考方案2】:

问题是您调用的Session 与更新值的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

【讨论】:

我想我错过了与线程的会话.. HttpContext.Current 是 NUll.. 我不能从 WebMethod 访问应用程序,因为它既不是静态的也不是 AClass.. 应该我使用不同的东西我必须使用 HttpContext.Current 我认为 是的,构建你自己的静态SessionState 类——我以前必须这样做。【参考方案3】:

我使用了@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();

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

你能验证UpdateSession() 正在运行吗? 另外,您的 javascript 中的 GetProgress() 是否因为值 对,警报每秒显示一次,值为 0

以上是关于c#中的Web进度条的主要内容,如果未能解决你的问题,请参考以下文章

C# MVVM 中的简单进度条

C# 中的 progressBar1 如何使用这个进度条控件.?

Xamarin Android C# 中的进度条和线程

c#如何根据文件数量控制进度条

从 .NET C# DLL 更新 MFC 对话框中的进度条

C#进度条怎么用 / C#progressBar的用法