Fourat
Fourat

Reputation: 2447

Doing heavy task and report progress in asp.net web page

I have an asp.net webforms page with a button and when clicking the button there's a Task that should be executes, I want the task to be execute asynchronously and that it reports its progress to a File (and maybe later to UI, but for now we stick to the file).

ASPX:

<asp:UpdatePanel runat="server" ID="upPage">
    <ContentTemplate>
        <div class="jumbotron">
            <asp:Button runat="server" ID="BtnExecute" CssClass="btn btn-primary btn-lg" Text="Execute Heavy Task" OnClick="BtnExecute_Click" />
            <asp:Label runat="server" ID="LblStatus" Text="Ready...."/>
        </div>
    </ContentTemplate>
</asp:UpdatePanel>

Code behind :

public partial class _Default : Page
{
    public Progress<int> HeavyTaskProgress { get; set; }
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void BtnExecute_Click(object sender, EventArgs e)
    {
        HeavyTaskProgress = new Progress<int>();
        HeavyTaskProgress.ProgressChanged += Progress_ProgressChanged;
        Task.Run(() => DoProcessing(HeavyTaskProgress)).ContinueWith(t => ProcessingFinished(t));
        LblStatus.Text = "Task is launched.... Please wait";
    }
    private void Progress_ProgressChanged(object sender, int e)
    {
        string message = string.Format("progress at {0}%{1}", e, Environment.NewLine);
        System.IO.File.AppendAllText(@"d:\progress.txt", message);
    }
    private void DoProcessing(IProgress<int> progress)
    {
        for (int i = 0; i < 10; ++i)
        {
            Thread.Sleep(1000); // CPU-bound work
            if (progress != null)
                progress.Report(i);
        }
    }
    private void ProcessingFinished(Task t)
    {
        System.IO.File.AppendAllText(@"d:\progress.txt", "Task done !! " + t.Status);
    }
}

In d:\progress.txt file I have only one line (Task done...) and progress is not reported (breakpoint in Progress_ProgressChanged is not breaking). I think that this is maybe caused by the fact that Progress_ProgressChanged and DoProcessing are executed in different threads but I don't know how to fix it.

Thank you for your help.

Upvotes: 1

Views: 373

Answers (1)

Jacobski
Jacobski

Reputation: 46

I think that your issue is that the thread processing the HTTP request is terminated when the event is raised.
The object subsribing to the event is in the thread which renders the page. This thread is terminated once the HTTP rsponse is sent back to the browser. So, when the event is raised, there is no subscriber any more.
As you have to send the HTTP response before the task is completed unless the user has to wait the task to complete to get some feedback, you should perform the action to write the progress into the file in the thread of the task.
If you want some regular feedback sent to the user, you can have a look at SignalR.
Here is an example to embed the writing progress code into the task:

public class DoingProcessing
{
    public Progress<int> HeavyTaskProgress { get; set; }

    private void Progress_ProgressChanged(object sender, int e)
    {
        string message = string.Format("progress at {0}%{1}", e, Environment.NewLine);
        System.IO.File.AppendAllText(@"d:\progress.txt", message);
    }

    public void DoProcessing()
    {
        HeavyTaskProgress = new Progress<int>();
        HeavyTaskProgress.ProgressChanged += Progress_ProgressChanged;
        DoProcessing(HeavyTaskProgress);
    }
    private void DoProcessing(IProgress<int> progress)
    {
        for (int i = 1; i <= 10; ++i)
        {
            Thread.Sleep(1000); // CPU-bound work
            if (progress != null)
                progress.Report(i*10);
        }
    }

    public void ProcessingFinished(Task t)
    {
        System.IO.File.AppendAllText(@"d:\progress.txt", "Task done !! " + t.Status);
    }
    public DoingProcessing()
    {

    }
} 

Upvotes: 3

Related Questions