我有一个带有按钮的asp.net webforms页面,当点击按钮时会有一个应该执行的Task
,我希望任务是异步执行的,并且它将进度报告给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 rsponse被发送回浏览器,该线程就会终止。因此,当事件被提出时,不再有订户。 由于您必须在任务完成之前发送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()
{
}
}