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

订阅后C# Event Handler仍为null问题求助

问题原因及解决办法

核心问题分析

你的BackgroundService是partial类,分为共享项目和Android平台两个实现部分:

  • 共享项目中的代码实现了单例模式Instance,并定义了DataReceived事件;
  • Android平台的代码继承自Android系统的Service组件,属于系统级服务。

当你调用StartService()时,通过Intent启动Android服务的过程中,Android系统会自动创建一个全新的BackgroundService实例——这个实例和你在ViewModel中订阅事件的BackgroundService.Instance完全是两个独立对象。因此,Android服务里调用OnDataReceived时,触发的是新实例的DataReceived事件,而该实例没有任何订阅者,导致事件处理程序为null。

解决办法

方案1:让Android服务复用共享项目的单例实例

修改Android平台的BackgroundService实现,拦截系统创建新实例的行为,强制复用单例:

[Service]
public partial class BackgroundService : Service
{
    public override void OnCreate()
    {
        // 检查当前实例是否为单例,若不是则终止自身
        if (BackgroundService.Instance != this)
        {
            StopSelf();
            return;
        }
        base.OnCreate();
    }

    // 原有代码保持不变...
}

同时调整StartService方法,确保先初始化单例再启动服务:

public void StartService()
{
    // 先获取单例,确保实例已创建
    _ = BackgroundService.Instance;
    Intent startService = new Intent(MainActivity.ActivityCurrent, typeof(BackgroundService));
    startService.SetAction("START_SERVICE");
    MainActivity.ActivityCurrent.StartService(startService);
}

方案2:使用消息传递替代事件(更稳妥的跨实例方案)

如果方案1存在兼容性问题,可以用.NET MAUI社区工具包的IMessenger实现跨实例消息传递,避免实例不一致的问题:

  1. 定义消息类
public class ServiceDataMessage : ValueChangedMessage<string>
{
    public ServiceDataMessage(string data) : base(data) { }
}
  1. ViewModel中订阅消息
// 注入IMessenger
public YourViewModel(IMessenger messenger)
{
    messenger.Register<ServiceDataMessage>(this, (recipient, message) =>
    {
        Message = message.Value;
    });
}
  1. Android服务中发送消息
private async Task DoStuff()
{
    var cancellationtoken = cancellationTokenSource.Token;
    var messenger = MauiProgram.Current.Services.GetService<IMessenger>();

    await Task.Run(() =>
    {
        var c = 0;
        while (!cancellationtoken.IsCancellationRequested)
        {
            Thread.Sleep(1000);
            c++;
            if (c > 50)
            {
                c = 0;
                cancellationTokenSource.Cancel();
            }

            double progress = (c + 1) * 10;
            messenger.Send(new ServiceDataMessage($"Android {progress}"));
        }
    }, cancellationtoken);
}
  1. DI中注册IMessenger
builder.Services.AddSingleton<IMessenger>(sp => WeakReferenceMessenger.Default);

方案3:修正DI配置(确保单例一致性)

如果依赖注入方式使用不当,也会导致实例不一致,确保DI注册的是同一个单例:

// 注册IBackgroundService为单例实例
builder.Services.AddSingleton<IBackgroundService>(BackgroundService.Instance);
// 同时注册BackgroundService本身,避免DI创建新实例
builder.Services.AddSingleton(BackgroundService.Instance);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:17:34