在 asp.net 网页中做繁重的任务并报告进度
Doing heavy task and report progress in asp.net web page
我有一个带有按钮的 asp.net 网络表单页面,当单击该按钮时,应该执行一个 Task
,我希望任务异步执行并将其进度报告给a File
(也许稍后会到 UI,但现在我们坚持使用文件)。
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>
后面的代码:
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);
}
}
在 d:\progress.txt
文件中我只有一行(任务完成...)并且没有报告进度(Progress_ProgressChanged
中的断点没有中断)。我认为这可能是由于 Progress_ProgressChanged
和 DoProcessing
在不同的线程中执行但我不知道如何解决。
感谢您的帮助。
我认为您的问题是处理 HTTP 请求的线程在引发事件时终止。
订阅事件的对象位于呈现页面的线程中。一旦 HTTP 响应被发送回浏览器,该线程就会终止。所以,当事件被引发时,就没有订阅者了。
由于您必须在任务完成之前发送 HTTP 响应,除非用户必须等待任务完成才能获得一些反馈,因此您应该在任务的线程中执行将进度写入文件的操作。
如果你想定期向用户发送一些反馈,你可以看看 SignalR。
下面是一个将写作进度代码嵌入到任务中的例子:
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()
{
}
}
我有一个带有按钮的 asp.net 网络表单页面,当单击该按钮时,应该执行一个 Task
,我希望任务异步执行并将其进度报告给a File
(也许稍后会到 UI,但现在我们坚持使用文件)。
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>
后面的代码:
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);
}
}
在 d:\progress.txt
文件中我只有一行(任务完成...)并且没有报告进度(Progress_ProgressChanged
中的断点没有中断)。我认为这可能是由于 Progress_ProgressChanged
和 DoProcessing
在不同的线程中执行但我不知道如何解决。
感谢您的帮助。
我认为您的问题是处理 HTTP 请求的线程在引发事件时终止。
订阅事件的对象位于呈现页面的线程中。一旦 HTTP 响应被发送回浏览器,该线程就会终止。所以,当事件被引发时,就没有订阅者了。
由于您必须在任务完成之前发送 HTTP 响应,除非用户必须等待任务完成才能获得一些反馈,因此您应该在任务的线程中执行将进度写入文件的操作。
如果你想定期向用户发送一些反馈,你可以看看 SignalR。
下面是一个将写作进度代码嵌入到任务中的例子:
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()
{
}
}