刷新页面时,另一个线程正在运行。

3

我的目标:

  1. 用户点击按钮。
  2. 按钮开始运行myTimeConsumingProcess()函数。
  3. 同一页面中的文本框每秒更新一次并添加一个“.”,直到进程完成。

我已经有的(这个可以工作,但不完全符合我的要求):

  1. 用户点击按钮,开始运行myTimeConsumingProcess()函数。
  2. 一个新的线程执行myTimeConsumingProcess()函数。
  3. 用户被重定向到一个“处理中”页面。
  4. 使用布尔类型的Session变量,该页面无休止地刷新,直到前一页中留下的线程将Session变量切换为false。

到目前为止的代码:

DatabaseChecker.aspx.cs

protected void btnStartProcess_Click(object sender, EventArgs e)
{
    Session["Running"] = true;
    Session["TextBoxContent"] = "Beginning myTimeConsumingProcess()...";
    Thread thread = new Thread(new ThreadStart(MyTimeConsumingProcess));
    thread.Start();
    Response.Redirect("Processing.aspx");
}

private void myTimeConsumingProcess()
{
    //do stuff!
    Session["TextBoxContent"] += "SUCCESS!"
    Session["Running"] = false;
}

Processing.aspx

每秒刷新一次页面:

<meta http-equiv="refresh" content="1" /> 

Processing.aspx.cs

在这个页面上保持不动,每1秒刷新一次,直到线程(留在DatabaseChecker.aspx.cs中)将会话变量“Running”更改为false。

protected void Page_Load(object sender, EventArgs e)
{
    TextBox1.Text = Session["TextBoxContent"].ToString();
    Session["TextBoxContent"] += ".";

    if ((bool)Session["Running"] == false)
    {
        Response.Redirect("DatabaseChecker.aspx");
    }
}

我想要但是无法实现的:

如果可能的话,我想避免重定向到另一个页面,而是只更新在点击按钮的页面中的文本框。我尝试使用 QueryString 重定向到同一页面以指示我在进程中的位置。然而,这并不起作用 --- 到达重定向到同一页面的代码,并且文本已经更新,但是似乎没有发生任何事情,直到进程完成(这使线程失去了意义)。

我尝试了我能想到的每种替代方法,包括 UpdatePanelTimerPageAsyncTask 控件,以及几乎所有我能想到的通过将这些控件与线程结合使用,并将 .aspx 页面的 Async 属性设置为 true 的组合。

2个回答

1
你尝试过使用 AJAX 吗?
当用户点击按钮时,触发一个 AJAX 函数来启动耗时的进程。
然后使用 AJAX 来轮询页面以获取进度。

添加了一些代码来解释我过去是如何做到这一点的。

实际上,我甚至不确定您是否需要更新面板,但我有一个。

这是我拥有的一些剪切代码片段,可以实现我认为您想要的功能。原始代码处理图像,并向用户显示进度条。

在项目中,我引用了AjaxControlToolkit和Ajax。

http://ajaxcontroltoolkit.codeplex.com/

这将向页面添加脚本管理器

<ajaxToolkit:ToolkitScriptManager runat="server" ID="scriptManageer" EnablePartialRendering="true" AsyncPostBackTimeout="900" />

这是页面的“重要”部分。
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <div id="message">&nbsp;</div>

        <button id="btnSave" class="saveButton" onclick="doSomething();return false;">Save</button>
    </ContentTemplate>
</asp:UpdatePanel>`

这个 JavaScript 使得轮询工作正常。
<script type="text/javascript">
    function startPoll()
    {
        Default.DoThing();
        myInterval = setInterval("poll()", 1000); //If you really want to poll that often
    }

    function poll()
    {
        progress = Default.ThingProcess();
        if (progress == "100%")
        {
            clearInterval(myInterval);
        }
        document.getElemenyById("message").innerHTML = progress;
    }
</script>

这是我的代码后台。

public partial class Default : System.Web.UI.Page
{
    protected void Page_load(object sender, EventArgs e)
    {
        Ajax.Utility.RegisterTypeForAjax(typeof(Default));
    }

    [Ajax.AjaxMethod]
    public void DoThing()
    {
        Thread thread = new Thread(new ThreadStart(MyTimeConsumingProcess));
        thread.Start();
        //The MyTimeConsumingProcess updates a var for thing progess
    }

    [Ajax.AjaxMethod]
    private String ThingProgress()
    {
        //Reads some var
        return progressNumber + "%"
    }
}

由于剪切和粘贴,可能会有一些不必要的东西,但这不应该影响其正常工作。

就像我说的那样,我尝试使用 AJAX 扩展控件 Timer、UpdatePanel 和 UpdateProgress,但都没有成功。我尝试过最有希望的想法是设置一个定时器每隔 1 秒触发一次,然后在另一个线程中运行进程,启用定时器并在每次触发时更新文本框,我非常有信心这会奏效——但它并没有。所有的更新都是在进程完成后才发生的,即使它在自己的线程中运行。 - CptSupermrkt
我在我的答案中编辑了一些代码。希望能有所帮助,我知道我以前做过这种事情。 - user1586294

0
也许如果您将Response.Redirect的第二个参数设置为true,它就不会等待页面处理。
public void Redirect(string url, bool endResponse);

不幸的是,这没有任何效果。我总是会随机地遇到奇怪的错误。有时它会说,“对象已经移动到这里”(这不是我的代码),而“这里”链接到应该执行的Response.Redirect,有时它只是挂起,直到另一个线程中的进程完成。 - CptSupermrkt

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