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

基于.NET Core 3.1+Azure SignalR无服务模式实现长时任务进度上报

后端代码修改说明

首先修正现有代码的核心问题:

  1. SignalR Trigger绑定的Hub名称需要和协商接口、输出绑定统一为TestHub,原代码中Trigger第一个参数错误配置为longrunningtask会导致事件无法触发
  2. 长时任务方法改为异步实现,避免阻塞函数线程
  3. 直接在长时任务方法中注入SignalR输出绑定,无需单独封装上报函数(也可保留原有上报函数按需调用)

修改后的完整后端代码如下:

using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace AzureSignalRFunctionTest
{
    public static class Function1
    {
        // 协商接口,保持不变
        [FunctionName("negotiate")]
        public static SignalRConnectionInfo Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
            [SignalRConnectionInfo(HubName = "TestHub")] SignalRConnectionInfo connectionInfo)
        {
            return connectionInfo;
        }

        // 修正HubName为TestHub,方法改为异步Task,注入SignalR输出绑定
        [FunctionName("longrunningtask")]
        public static async Task LongRunningTask(
            [SignalRTrigger("TestHub", "messages", "SendMessage")] InvocationContext invocationContext, 
            [SignalRParameter] string message, 
            [SignalR(HubName = "TestHub")] IAsyncCollector<SignalRMessage> signalRMessages,
            ILogger logger)
        {
            logger.LogInformation($"Receive {message} from {invocationContext.ConnectionId}.");

            // 上报任务开始
            await signalRMessages.AddAsync(new SignalRMessage
            {
                ConnectionId = invocationContext.ConnectionId,
                Target = "reportProgress",
                Arguments = new[] { "任务开始,进度0%" }
            });

            // 模拟长时任务分阶段执行
            await Task.Delay(10000);
            await signalRMessages.AddAsync(new SignalRMessage
            {
                ConnectionId = invocationContext.ConnectionId,
                Target = "reportProgress",
                Arguments = new[] { "执行中,进度33%" }
            });

            await Task.Delay(10000);
            await signalRMessages.AddAsync(new SignalRMessage
            {
                ConnectionId = invocationContext.ConnectionId,
                Target = "reportProgress",
                Arguments = new[] { "执行中,进度66%" }
            });

            await Task.Delay(10000);
            // 上报任务完成
            await signalRMessages.AddAsync(new SignalRMessage
            {
                ConnectionId = invocationContext.ConnectionId,
                Target = "reportProgress",
                Arguments = new[] { "任务执行完成,进度100%" }
            });
        }

        // 原有上报函数可保留用于其他场景复用,按需调用即可
        [FunctionName("reportprogress")]
        public static Task ReportProgress(string connectionId, string message,
            [SignalR(HubName = "TestHub")] IAsyncCollector<SignalRMessage> signalRMessages)
        {
            return signalRMessages.AddAsync(
                new SignalRMessage
                {
                    ConnectionId = connectionId,
                    Target = "reportProgress",
                    Arguments = new[] { message }
                });
        }

    }
}
前端HTML实现代码

前端需要完成SignalR连接初始化、事件监听、触发长时任务三个逻辑,示例代码如下:

<!DOCTYPE html>
<html>
<head>
    <title>SignalR进度上报测试</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.min.js"></script>
</head>
<body>
    <button id="startBtn">启动长时任务</button>
    <div id="progressText"></div>
    <script>
        const connection = new signalR.HubConnectionBuilder()
            .withUrl('你的Azure Function域名/api') // 替换为你自己的Function访问域名
            .build();

        // 监听进度上报事件
        connection.on('reportProgress', (message) => {
            document.getElementById('progressText').innerText = message;
        });

        // 启动连接
        connection.start()
            .then(() => console.log('连接成功'))
            .catch(err => console.error(err));

        // 点击按钮触发长时任务
        document.getElementById('startBtn').addEventListener('click', () => {
            connection.invoke('SendMessage', '测试任务')
                .catch(err => console.error(err));
        });
    </script>
</body>
</html>
注意事项
  • Azure SignalR服务必须配置为无服务器模式,和你当前的选型一致
  • .NET Core 3.1对应的SignalR扩展包请使用1.x版本(推荐1.12.0),2.x及以上版本需要.NET 6+运行时支持
  • 如果你的任务运行时长超过Azure Function消费计划的最大超时时间(默认5分钟,可配置最高10分钟),建议改用Durable Functions编排长时任务,避免函数执行超时被强制终止
  • Function的CORS配置需要放开你前端页面的域名,避免跨域请求失败

内容的提问来源于stack exchange,提问作者Philip Johnson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:51:00