订阅后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实现跨实例消息传递,避免实例不一致的问题:
- 定义消息类
public class ServiceDataMessage : ValueChangedMessage<string> { public ServiceDataMessage(string data) : base(data) { } }
- ViewModel中订阅消息
// 注入IMessenger public YourViewModel(IMessenger messenger) { messenger.Register<ServiceDataMessage>(this, (recipient, message) => { Message = message.Value; }); }
- 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); }
- 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
相关产品推荐
相关产品推荐

