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进度条的主要内容,如果未能解决你的问题,请参考以下文章