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

ExcelDNA RTD对接ASP.NET SignalR后topic更新未触发注册函数问题求助

问题原因&修正方案

1. 基础代码错误

你当前的RTD类名是SignalRServer,但构造函数名写为TradesRtdServer,会直接导致编译失败,先将构造函数名修正为和类名一致。

2. ProgID不匹配且未显式声明

仅添加[ComVisible(true)]特性不足以保证RTD服务的ProgID符合预期,系统自动生成的ProgID可能和你在XlCall.RTD中传入的参数不一致,且你当前传入的Excel.AddIn.Trading.SignalRServer和实际类的命名空间DMT.Excel.AddIn+类名SignalRServer完全不符,Excel无法匹配到对应的RTD服务实例。
修正方法:给RTD类显式添加[ProgId]特性,且XlCall.RTD的第一个参数和该特性值完全一致。

3. SignalR回调参数类型不兼容

你当前在_connection.On中使用object类型接收推送数据,若推送的是自定义复杂对象,Excel无法直接识别,会忽略更新。建议显式指定为Excel支持的基础类型(如字符串、数字),复杂对象可先序列化为JSON字符串再传入UpdateValue。


修正后代码

RTD服务代码

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
using ExcelDna.Integration;
using ExcelDna.Integration.Rtd;

namespace DMT.Excel.AddIn
{
    [ComVisible(true)]
    // 显式指定ProgId,和XlCall.RTD的第一个参数完全匹配
    [ProgId("DMT.Excel.AddIn.SignalRServer")]
    public class SignalRServer : ExcelRtdServer
    {
        private HubConnection _connection;
        private List<Topic> _topics = new List<Topic>();

        // 构造函数名和类名保持一致
        public SignalRServer()
        {
            _connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:5000/api/test/hub")
                .WithAutomaticReconnect()
                .Build();

            // 显式指定接收数据类型为Excel可识别的基础类型
            _connection.On<string>("Test", m =>
            {
                foreach (Topic topic in _topics)
                {
                    topic.UpdateValue(m);
                }
            });

            // 添加异常捕获避免连接失败无日志
            _ = Task.Run(async () => 
            {
                try
                {
                    await _connection.StartAsync();
                }
                catch (Exception ex)
                {
                    DmtAddIn.Logger.Error(ex, "SignalR连接启动失败");
                }
            });
        }

        protected override bool ServerStart()
        {
            DmtAddIn.Logger.Information("ServerStart");
            return true;
        }

        protected override void ServerTerminate()
        {
            // 退出时释放SignalR连接
            _connection?.DisposeAsync();
            DmtAddIn.Logger.Information("ServerTerminate");
        }

        protected override object ConnectData(Topic topic, IList<string> topicInfo, ref bool newValues)
        {
            DmtAddIn.Logger.Information("ConnectData: {0} - {{{1}}}", topic.TopicId, string.Join(", ", topicInfo));
            if(!_topics.Contains(topic))
                _topics.Add(topic);
            return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA);
        }

        protected override void DisconnectData(Topic topic)
        {
            _topics.Remove(topic);
            DmtAddIn.Logger.Information("DisconnectData: {0}", topic.TopicId);
        }
    }
}

自定义函数代码

[ExcelFunction(Name = "SignalR.Test.RTD")]
public static object GetSignalRMessages()
{
    // ProgID和RTD类的[ProgId]特性值完全一致
    return XlCall.RTD("DMT.Excel.AddIn.SignalRServer", null, "Test");
}

额外检查项

  • 调试时在ConnectData方法添加断点,确认单元格输入=SignalR.Test.RTD()时该方法被触发,若未触发则说明ProgID注册失败,可清理旧插件注册表后重新编译加载
  • 确认SignalR推送的数据可以正常转换为你指定的接收类型,避免类型转换失败导致更新不生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:06:05