Reputation: 2447
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
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