AsyncTask with a Updatepanel?
asp.net, asynchronous, c#, postback
Solution
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.
Problem
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 ...