ASP.NET Asynchronous label update

2019-02-10 23:59发布

I have a process that runs long, and I want to update a label on the page as the process goes along, but I'm not having any luck.

Here's the aspx:

<%@ Page Language="C#" Async="true" AutoEventWireup="true" CodeFile="Async.aspx.cs" Inherits="Website.structureDoc.Async" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="startAsyncButton" runat="server" Text="Run" onclick="startAsyncButton_Click"/>
        <asp:Button ID="cancelAsyncButton" runat="server" Text="Cancel" onclick="cancelAsyncButton_Click"/>

        <asp:label id="resultLabel" runat="server"></asp:label>

    </div>
    </form>
</body>
</html>

And here's the code behind:

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

namespace Website.structureDoc
{
    public partial class Async : System.Web.UI.Page
    {
        BackgroundWorker backgroundWorker1;
        protected void Page_Load(object sender, EventArgs e)
        {
            backgroundWorker1 = new BackgroundWorker();

            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        protected void startAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                // Start the asynchronous operation.
                backgroundWorker1.RunWorkerAsync();
            }
        }

        protected void cancelAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                // Cancel the asynchronous operation.
                backgroundWorker1.CancelAsync();
            }
        }

        // This event handler is where the time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

        // This event handler updates the progress.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
        }

        // This event handler deals with the results of the background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                resultLabel.Text = "Done!";
            }
        }
    }
}

Are Background Workers not the right approach for this?

I'd rather not do this using AJAX if possible.

2条回答
成全新的幸福
2楼-- · 2019-02-11 00:27

You can use SignalR library for this to get this work.

See the sample here

In the given sample, after the server side dosomething() async task is done, it calls the client side notifyResult() to update the view.

Also see : Is there a way to exclude a Client from a Clients.method call in SignalR?

查看更多
来,给爷笑一个
3楼-- · 2019-02-11 00:52

This is not going to work. The problem is that asp.net works on a request/response model. In order to receive any updates the client (browser) needs to request the information from the server. In order for your label to be updated you will need to send a request for its new value to the server which in turn works out what the value is and responds with the appropriate value for you to display.

The easiest method would be to write this using AJAX with some way of timing the requests for data, or instead to set a timer and have the page refresh itself on a set timer. The bottom line is you need the page to poll for the updated value, just because you update the value in your worker process does not mean the browser will receive this new value.

I know you said you didnt want to use AJAX but take a look at the following jQuery.get() to get a better understanding of what you need to do.

查看更多
登录 后发表回答