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

.NET MAUI在AppShell中调用DisplayAlert触发TargetInvocation异常求助

.NET MAUI AppShell中SignalR回调调用DisplayAlert异常的解决办法

问题根源

SignalR的NewCallNotificationReceived回调运行在非UI线程,而DisplayAlert是依赖UI上下文的操作,直接调用会因线程上下文不匹配抛出TargetInvocation异常;Label显示能正常运行是因为部分控件更新会隐式处理线程同步,但弹窗类操作要求严格的UI线程上下文。

修复方案

修改代码,确保SignalR回调中的弹窗操作在UI线程执行,同时优化Hub连接的异步逻辑:

private readonly HubConnection _hubConnection;
private string baseUrl = "https:/";

public AppShell()
{
    InitializeComponent();

    NavigationPage.SetHasBackButton(this, false);

    _hubConnection = new HubConnectionBuilder()
        .WithUrl($"{baseUrl}/notificationhub")
        .Build();

    // 回调中强制切换到UI线程执行弹窗
    _hubConnection.On<Notification>("NewCallNotificationReceived", async (notify) =>
    {
        await MainThread.InvokeOnMainThreadAsync(async () =>
        {
            await DisplayAlert("Title", notify.Message, "OK");
        });
    });

    // 异步初始化Hub连接,避免冗余线程嵌套
    _ = InitializeHubAsync();
}

// 用async Task替代async void,避免异常丢失
private async Task InitializeHubAsync()
{
    try
    {
        await _hubConnection.StartAsync();
    }
    catch (Exception ex)
    {
        // 连接失败时也在UI线程提示
        await MainThread.InvokeOnMainThreadAsync(async () =>
        {
            await DisplayAlert("连接失败", $"错误信息: {ex.Message}", "确定");
        });
    }
}

关键修改点

  • 使用MainThread.InvokeOnMainThreadAsync将弹窗操作强制切换到UI线程,这是.NET MAUI跨平台的推荐写法,比直接用Dispatcher更可靠。
  • 移除了async void的ShowPopup方法,改用async Task管理异步操作,避免异步异常无法被捕获的问题。
  • 重构Hub连接启动逻辑,去掉冗余的Task.Run嵌套Dispatcher写法,代码更简洁且符合异步规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:52:15