Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
398 views
in Technique[技术] by (71.8m points)

c# - AsyncTask with a Updatepanel?

Yo, i have created a WebProject to test if its possible to create a asyncTask to update a Progressbar:

public partial class AsyncTest : System.Web.UI.Page
{
    private String _taskprogress;
    private AsyncTaskDelegate _dlgt;
    protected delegate void AsyncTaskDelegate();

    protected void Page_Load(object sender, EventArgs e)
    {
    }

    public String GetAsyncTaskProgress()
    {
        return _taskprogress;
    }

    public IAsyncResult OnBegin(object sender, EventArgs e,
       AsyncCallback cb, object extraData)
    {
        _taskprogress = "AsyncTask started at: " + DateTime.Now + ". ";

        _dlgt = new AsyncTaskDelegate(ReadFile);
        IAsyncResult result = _dlgt.BeginInvoke(cb, extraData);

        return result;
    }

    public void ReadFile()
    {
        try
        {
            string Filename = @"D:Material.txt";
            int filelength = TotalLines(Filename); //just reads the lines of the file

            ProgressBar1.Maximum = filelength;

            using (StreamReader reader = new StreamReader(Filename))
            {
                string line;
                int actualfileline = 1;
                while ((line = reader.ReadLine()) != null)
                {
                    string test = line;
                    ProgressBar1.Value = actualfileline;
                    actualfileline++;
                    //UpdatePanel1.Update(); <- Doesnt work
                    System.Threading.Thread.Sleep(5);
                }
            }
        }
        catch (Exception ex)
        {
            string exm = ex.Message.ToString();
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        OnBegin(this, null, null, null);

    }
}

Aaaand my aspx-code: (i have a scriptmanager for sure also)

<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:Button runat="server" ID="btnDoTask" Text="Do Task" OnClick="Button1_Click" />
        <br />
        <br />
        <eo:ProgressBar ID="ProgressBar1" runat="server" Width="250px" 
            BackgroundImage="00060301" BackgroundImageLeft="00060302" 
            BackgroundImageRight="00060303" ControlSkinID="None" IndicatorImage="00060304">
        </eo:ProgressBar
    </ContentTemplate>
</asp:UpdatePanel>

Calling the Updatepanel1.Update() doesnt work, because it says:

You can only call the Update-methoe bevor rendering

So how else can i update it then ? I want the user to see the progress on the progressbar - because i want to implement a bigger file-reading piece of code. Im really new to async-programming, so im not sure if there is everything you need :/

Edit:

Okay, now I created a Webservice in my page:

[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public string GetProcess()
{
    if (actualfileline != null)
    {
        return actualfileline.ToString();
    }
    else
    {
        return "0";
    }
}

And i want to call it trough my Button:

<asp:Button runat="server" ID="btnDoTask" Text="Do Task" OnClick="Button1_Click" OnClientClick="StartJavaScriptProgress()" />

The javascript-part:

function StartJavaScriptProgress()
{
    var elm = document.getElementById("LabelProgress");
    elm.innerText = "Currently Working ...";
    setTimeout(WebService(), 1000);
};

function WebService() {
    $.ajax(
    {
        type: "POST",
        url: "AsyncTest.aspx/GetProcess",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            alert("Worked");
            var elm = document.getElementById("ProgressBar1");
            elm.value = response.d; 
        },
        error: function (jqXHR, textStatus, errorThrown) {

            alert("Error starting process");
        }
    })
};

But it doesnt work ...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Reading a file synchronously on another thread will not improve the performance of your web app, check this for more details. Instead, you should be using a naturally asynchronous API like ReadLineAsync, and enable asynchronous completion of the HTTP request with RegisterAsyncTask, like this:

// Make sure to enable asynchronous request processing:
// <%@ Page Async="true" ... %>

public partial class AsyncTest : System.Web.UI.Page
{
    private String _taskprogress;

    protected void Page_Load(object sender, EventArgs e)
    {
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        RegisterAsyncTask(new PageAsyncTask(ReadFileAsync));
    }

    public async Task ReadFileAsync()
    {
        try
        {
            string Filename = @"D:Material.txt";
            int filelength = TotalLines(Filename); //just reads the lines of the file

            ProgressBar1.Maximum = filelength;

            using (StreamReader reader = new StreamReader(Filename))
            {
                string line;
                int actualfileline = 1;
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    string test = line;
                    ProgressBar1.Value = actualfileline;
                    actualfileline++;
                    //UpdatePanel1.Update(); <- Doesnt work
                    System.Threading.Thread.Sleep(5);
                }
            }
        }
        catch (Exception ex)
        {
            string exm = ex.Message.ToString();
        }
    }
}

Note, this still won't update the progress UI in the client side page. What this does is making the current HTTP request to finish asynchronously on the server side. The browser will still be waiting for it. This improves the scalability of your web app, but the web page on the client side will be rendered only when ReadFileAsync has been fully completed.

If you want to provide the progress updates on the client side, you should use AJAX and start the above lengthy process via XHR request, or inside a hidden frame. You would then be able to track its progress with a secondary XHR request and update the UI. Inside ReadFileAsync, you'd need to keep the progress info inside a session variable, e.g. Session["actualfileline"] = actualfileline. You'd access Session["actualfileline"] from your secondary XHR requests.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...