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

Xamarin MessagingCenter问题:发送一次消息却多次接收

解决Xamarin MessagingCenter订阅重复接收消息的问题

这个问题我之前也碰到过,根源在于Popup页面的生命周期和普通导航页面不一样,导致你的订阅逻辑重复执行了。

问题分析

你在Page1的OnAppearing里订阅消息,OnDisappearing里取消订阅——但当你弹出Page2这个Popup页面时,底层的Page1并没有从导航栈中被移除,只是被Popup覆盖了,所以Page1的OnDisappearing方法根本不会被触发!

这就造成了:

  1. 第一次打开Popup,Page1的OnDisappearing没执行,订阅没有被取消;
  2. 关闭Popup时,Page1的OnAppearing再次触发,又添加了一次订阅;
  3. 现在同一个Page1实例有两个相同的订阅,所以发送一次消息,回调会被执行两次。

你可以验证一下:在OnAppearing和OnDisappearing里各加一行日志,会发现打开Popup时OnDisappearing根本没跑。

解决方案

有两种靠谱的处理方式,根据你的需求选:

方案1:把订阅移到构造函数,取消订阅移到Dispose

因为页面的构造函数只会执行一次,这样从根源上避免重复订阅:

// Page1的构造函数
public Page1()
{
    InitializeComponent();
    // 在这里订阅,只执行一次
    MessagingCenter.Subscribe<Page2, ParamType>(this, "PopUpData", async (sender, arg) => {
        Task.WaitAll(tasks.ToArray());
        switch (arg.Tipo) { 
            case 2: 
                Console.WriteLine(" *********** msg received");
                tasks.Add(Task.Run(() => ShareMap(arg))); 
                break; 
            case 3: 
                tasks.Add(Task.Run(() => ShareEvent(arg))); 
                break; 
            case 6: 
                tasks.Add(Task.Run(() => ShareImage(arg))); 
                break; 
        } 
    });
}

// 重写Dispose方法,页面销毁时取消订阅
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        MessagingCenter.Unsubscribe<Page2, ParamType>(this, "PopUpData");
    }
    base.Dispose(disposing);
}

方案2:在OnAppearing里先取消再订阅

如果必须在页面出现时订阅,那每次订阅前先取消旧的订阅,确保不会重复:

protected override void OnAppearing() { 
    base.OnAppearing(); 
    // 先取消已有订阅,再添加新的
    MessagingCenter.Unsubscribe<Page2, ParamType>(this, "PopUpData");
    MessagingCenter.Subscribe<Page2, ParamType>(this, "PopUpData", async (sender, arg) => { 
        Task.WaitAll(tasks.ToArray()); 
        switch (arg.Tipo) { 
            case 2: 
                Console.WriteLine(" *********** msg received"); 
                tasks.Add(Task.Run(() => ShareMap(arg))); 
                break; 
            case 3: 
                tasks.Add(Task.Run(() => ShareEvent(arg))); 
                break; 
            case 6: 
                tasks.Add(Task.Run(() => ShareImage(arg))); 
                break; 
        } 
    }); 
}

// OnDisappearing可以保留,但现在主要靠OnAppearing里的取消逻辑避免重复
protected override void OnDisappearing() { 
    base.OnDisappearing(); 
    MessagingCenter.Unsubscribe<Page2, ParamType>(this, "PopUpData"); 
}

额外提醒

MessagingCenter的订阅是基于订阅者实例、发送者类型、消息键三者的组合来区分的。同一个订阅者实例对同一个消息订阅多次,就会收到多次回调——这也是你遇到问题的核心原因,所以一定要确保订阅逻辑不会重复执行。

内容的提问来源于stack exchange,提问作者Éder Rocha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 21:42:52