在 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_ProgressChangedDoProcessing 在不同的线程中执行但我不知道如何解决。

感谢您的帮助。

我认为您的问题是处理 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()
    {

    }
}