.NET MAUI Android端SQLite初始化异常:主页无法加载
问题分析与解决方案
核心问题:构造函数同步阻塞异步方法引发死锁
你的WitbitsRepository构造函数中调用CreateTablesAsync().Wait(),这会在UI线程上触发死锁:
CreateTablesAsync()执行到await db.CreateTableAsync<Book>()时会释放当前UI线程- 但
.Wait()强制同步等待,直接阻塞UI线程 - 异步操作完成后需要回到UI线程继续执行,却发现线程已被阻塞,最终导致应用卡死,MainPage无法加载
修复步骤
1. 重构WitbitsRepository,规避构造函数阻塞
将数据库初始化逻辑移至异步方法,彻底放弃构造函数内的同步等待操作:
public class WitbitsRepository { private SQLiteAsyncConnection db; // 私有构造函数,仅通过异步工厂方法创建实例 private WitbitsRepository() { Debug.WriteLine("WitbitsRepository constructor called"); } // 异步工厂方法,完成全量初始化 public static async Task<WitbitsRepository> CreateAsync() { var repo = new WitbitsRepository(); await repo.InitializeAsync(); return repo; } private async Task InitializeAsync() { var databasePath = Path.Combine(FileSystem.AppDataDirectory, "Witbits.db"); Debug.WriteLine("Database path: " + databasePath); if (!File.Exists(databasePath)) { Debug.WriteLine("Database file not found at: " + databasePath); CopyDatabaseFromResource(databasePath); } else { Debug.WriteLine("Database file found at: " + databasePath); } db = new SQLiteAsyncConnection(databasePath); await CreateTablesAsync(); } private async Task CreateTablesAsync() { await db.CreateTableAsync<Book>(); } // 实现嵌入式资源复制逻辑 private void CopyDatabaseFromResource(string targetPath) { // 注意替换为你的项目命名空间与资源路径 using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("YourAppNamespace.Witbits.db"); using var fileStream = new FileStream(targetPath, FileMode.Create); stream.CopyTo(fileStream); } }
2. 修正App.xaml.cs的初始化逻辑
确保异步流程不阻塞,正确获取Repository实例:
public partial class App : Application { public App() { InitializeComponent(); _ = InitializeAppAsync(); // 用下划线避免异步警告,确保流程执行完成 } private async Task InitializeAppAsync() { await InitializeDatabaseAsync(); MainPage = new MainPage(); } private async Task InitializeDatabaseAsync() { // 通过异步工厂方法创建Repository var repository = await WitbitsRepository.CreateAsync(); // 若需全局复用,可将实例赋值给静态属性 // App.GlobalRepository = repository; } // 可选:全局Repository实例 // public static WitbitsRepository GlobalRepository { get; private set; } }
3. 额外检查项
- 确认嵌入式数据库文件的生成操作设置为「嵌入式资源」:在VS中选中
Witbits.db,右键属性修改生成操作 - 验证资源名称正确性:可通过
Assembly.GetExecutingAssembly().GetManifestResourceNames()输出所有资源名称,匹配你的数据库资源路径 - 确保
Book类符合sqlite-net-pcl要求:需包含主键属性(用[PrimaryKey]标记)
内容的提问来源于stack exchange,提问作者Andrew Dvorak
相关产品推荐
相关产品推荐

