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

SQLite-NET-PCL中CreateTableAsync<Type>调用卡顿问题排查

问题分析与解决方案

核心原因:同步调用异步方法导致死锁

你的代码卡在CreateTableAsync后无法继续执行,本质是主线程死锁:

  • MovieViewModel构造函数中使用DBService.GetMovies().Result同步等待异步任务完成,直接阻塞了UI主线程。
  • SQLiteAsyncConnection的操作默认在UI线程上下文执行,await之后需要回到主线程继续执行后续代码,但主线程已经被.Result阻塞,形成死锁——异步任务无法完成后续步骤,主线程也一直等待异步结果。

分步修正方案

1. 修复DBService:移除ContinueWith,规范异步写法

混合await和ContinueWith会增加代码复杂度,直接用await更清晰且避免上下文问题:

using Xamarin.Essentials;
using System.Diagnostics;

public static class DBService
{
    private static SQLiteAsyncConnection dbConn;

    public static async Task Init()
    {
        if (dbConn != null)
            return;

        string databasePath = Path.Combine(FileSystem.AppDataDirectory, "Movies.db");
        dbConn = new SQLiteAsyncConnection(databasePath, false);

        var createResult = await dbConn.CreateTableAsync<Movie>();
        Debug.WriteLine(createResult.ToString());
        Debug.WriteLine("After table created"); // 现在会正常执行
    }

    public static async Task<IEnumerable<Movie>> GetMovies()
    {
        await Init();
        return await dbConn.Table<Movie>().ToListAsync();
    }
}

2. 修复ViewModel:避免构造函数同步调用异步方法

MVVM架构中,构造函数不能阻塞主线程,改用异步初始化方法加载数据,同时实现INotifyPropertyChanged确保UI更新:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class MovieViewModel : INotifyPropertyChanged
{
    private List<Movie> _movies;
    public List<Movie> Movies 
    { 
        get => _movies; 
        set 
        { 
            _movies = value;
            OnPropertyChanged();
        }
    }
    
    public MovieViewModel()
    {
        // 构造函数仅做初始化触发,不执行阻塞操作
        LoadMoviesAsync();
    }

    // 异步加载数据,async void仅在事件/初始化场景使用
    private async void LoadMoviesAsync()
    {
        var movieList = await DBService.GetMovies();
        Movies = movieList.ToList();
    }

    // MVVM必备:实现属性变更通知
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3. 额外检查点

  • 确认SQLite.NET-PCL版本与你的Xamarin.Forms、.NET Framework版本兼容,建议使用最新稳定版。
  • 实体类中Length字段为DateTime类型,命名容易误解为时长(建议改为ReleaseDate或Duration),但SQLite本身支持DateTime类型,不是死锁原因。
  • 验证数据库路径权限:Android需确保申请了读写外部存储权限(API 30+用Scoped Storage),iOS沙箱默认允许应用自身目录读写,无需额外权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:30:42