You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web表单长任务取消与结果反馈问题技术咨询

解决方案

1. 替换文件取消机制,用原生CancellationTokenSource

文件检测存在IO开销、状态不同步问题,改用.NET原生取消令牌更可靠,同时把任务和令牌绑定到用户Session,实现单用户单任务限制。

后端代码示例

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

protected void Execute_Click(object sender, EventArgs e)
{
    // 检查用户是否已有运行中的任务
    if (Session["ActiveTask"] != null)
    {
        ResultLabel.Text = "已有任务正在执行,请稍后再试";
        return;
    }

    var cts = new CancellationTokenSource();
    var token = cts.Token;

    // 定义带结果返回的异步任务
    Task<(bool IsSuccess, string Msg, Exception Error)> longTask = Task.Run(async () =>
    {
        try
        {
            // 模拟15分钟的循环任务(每秒执行一次片段)
            for (int i = 0; i < 900; i++)
            {
                // 先检查是否收到取消请求
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                }

                // 这里写你的实际任务逻辑
                await Task.Delay(1000); // 模拟单次耗时操作
            }

            return (true, "任务执行完成", null);
        }
        catch (OperationCanceledException)
        {
            return (false, "任务已取消", null);
        }
        catch (Exception ex)
        {
            return (false, "任务执行失败", ex);
        }
    }, token);

    // 任务完成后的回调,更新页面和Session状态
    longTask.ContinueWith(task =>
    {
        // 清除Session中的任务标记
        Session.Remove("ActiveTask");
        Session.Remove("TaskCts");

        // 解析任务结果
        var result = task.Result;
        string displayMsg;
        if (result.IsSuccess)
        {
            displayMsg = result.Msg;
        }
        else if (result.Error != null)
        {
            displayMsg = $"失败原因:{result.Error.Message}";
        }
        else
        {
            displayMsg = result.Msg;
        }

        // 异步更新页面结果标签
        ScriptManager.RegisterStartupScript(this, GetType(), "ShowResult", 
            $"document.getElementById('{ResultLabel.ClientID}').innerText = '{displayMsg.Replace("'", "\\'")}';", 
            true);
    }, TaskScheduler.FromCurrentSynchronizationContext());

    // 把任务和取消令牌存入Session,用于后续取消操作
    Session["ActiveTask"] = longTask;
    Session["TaskCts"] = cts;
    ResultLabel.Text = "任务已启动,正在执行...";
}

protected void Cancel_Click(object sender, EventArgs e)
{
    var cts = Session["TaskCts"] as CancellationTokenSource;
    if (cts != null && !cts.IsCancellationRequested)
    {
        cts.Cancel();
        ResultLabel.Text = "已发送取消请求,任务将停止";
    }
    else
    {
        ResultLabel.Text = "没有正在运行的任务";
    }
}

2. 解决页面刷新丢失反馈的问题

用UpdatePanel实现局部刷新,避免整页刷新清空结果内容:

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Label ID="ResultLabel" runat="server" Text=""></asp:Label>
        <br />
        <asp:Button ID="ExecuteBtn" runat="server" Text="执行任务" OnClick="Execute_Click" />
        <asp:Button ID="CancelBtn" runat="server" Text="取消任务" OnClick="Cancel_Click" />
    </ContentTemplate>
</asp:UpdatePanel>

3. 关键注意点

  • 把Session超时时间设为超过15分钟,避免Session过期导致无法取消任务或追踪结果。
  • 任务中涉及的资源(如数据库连接、文件句柄)要在任务结束/取消时及时释放。
  • 如果需要用户关闭页面后仍能追踪任务状态,可以把任务信息存入数据库,而不是依赖Session。

内容的提问来源于stack exchange,提问作者Robert Cotterman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:05:34