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

如何修复.NET MAUI 9 Android弹窗中的CalledFromWrongThreadException异常?

.NET 9 MAUI Android:设置图片Source触发线程异常(主线程调度无效)

问题背景

开发的带弹窗的.NET MAUI Android应用在.NET 8下运行正常,但迁移到.NET 9后,弹窗内设置Image和ImageButton的Source属性时,会抛出线程异常,且部分图片加载时应用直接崩溃。已尝试用MainThread.BeginInvokeOnMainThread、MainThread.InvokeOnMainThreadAsync和Dispatcher.Dispatch包裹代码,均未解决。

弹窗内代码片段

// imageGrid 是Grid控件,imagelist是StackLayout控件
foreach (......)
{
    var image = new Image
    {
        Source = "......" // 图片URL
    };

    imageGrid.SetRow(image, 0);
    imageGrid.SetColumn(image, 0);
    imageGrid.Children.Add(image);
}
imagelist.Children.Add(new ScrollView
{
    Content = new StackLayout
    {
        Children =
        {
            new ImageButton
            {
                Source=ImageSource.FromUri(new Uri("......")) // 图片URL
            }
        }
    }
});

异常信息

com.bumptech.glide.load.engine.CallbackException: Unexpected exception thrown by non-Glide code
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

解决方案尝试与验证

1. 确保完整UI操作都在主线程执行

可能之前仅包裹了部分代码,需将所有UI元素的创建、布局添加、属性设置全量放入主线程调度中,避免控件未挂载到视图树就操作属性:

MainThread.BeginInvokeOnMainThread(() => 
{
    foreach (......)
    {
        var image = new Image();
        // 先添加到布局,再设置Source
        imageGrid.SetRow(image, 0);
        imageGrid.SetColumn(image, 0);
        imageGrid.Children.Add(image);
        image.Source = "......"; // 图片URL
    }

    // 拆分ImageButton的创建与Source设置
    var imageButton = new ImageButton();
    var scrollContainer = new StackLayout { Children = { imageButton } };
    imagelist.Children.Add(new ScrollView { Content = scrollContainer });
    // 控件挂载后再设置Source
    imageButton.Source = ImageSource.FromUri(new Uri("......"));
});

2. 延迟设置Source(确保控件已绑定到视图树)

.NET 9对UI线程的检查更严格,控件未完全挂载到视图树时设置Source,可能触发底层Glide的线程问题。可通过MAUI的Dispatcher.DispatchDelayed延迟设置:

// 在添加控件到布局后,延迟100ms设置Source
Dispatcher.DispatchDelayed(TimeSpan.FromMilliseconds(100), () => 
{
    image.Source = "......";
    imageButton.Source = ImageSource.FromUri(new Uri("......"));
});

3. 检查自定义Glide配置(若有)

如果项目中自定义了Glide的加载逻辑,需确保所有回调和UI操作都切换到主线程。.NET 9中MAUI对Glide的集成逻辑有调整,自定义配置可能干扰线程调度。

4. 确认弹窗创建在主线程

若弹窗是在后台线程中实例化的,即使后续属性设置在主线程也会触发异常。需确保弹窗的创建、显示全流程都在主线程执行:

MainThread.BeginInvokeOnMainThread(() => 
{
    var popup = new YourPopup();
    // 弹窗内的UI构建逻辑也放在这里
    popup.Show();
});

原因分析

.NET 9收紧了MAUI Android的UI线程检查机制,同时底层图片加载库Glide的回调调度逻辑在.NET 9中有变化。如果控件未完全挂载到视图树就设置Source,或部分UI操作仍在后台线程执行,就会触发CalledFromWrongThreadException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 09:13:13