Xamarin与AzureMobileServices脱机同步:初始离线加载速度极慢

时间:2018-05-31 00:43:13

标签: sqlite asynchronous xamarin.forms azure-mobile-services offline-caching

我成功使用Azure Mobile Services和Xamarin Forms在Azure托管的SQL数据库上执行CRUD操作。脱机同步部分将数据存储在手机上的SQLite数据库中。为了让它像我们现在一样平稳地工作,一直有一些障碍,但这仍然是最后一道障碍。

问题

当设备没有连接时(在各种物理和仿真设备上使用飞行模式进行测试) - 第一次访问任何离线数据时,非常很长时间什么都归还如果数据存在于SQLite DB中,则会出现这种情况。

没有抛出任何异常,或者我可以看到打印到日志中的任何内容,表明延迟可能是什么。

要提出一个想法,在线时,20行上的PullAsync()可能需要5秒,并且该数据将存储到SQLite DB中。将设备置于离线模式后,相同的操作可能需要60秒。这些数字非常随意,但延迟时间明显太长。

要添加此功能,此长时间加载仅发生第一次调用任何脱机同步方法。在那之后,每种方法都接近即时,正如我所期望的那样 - 但为什么不是第一次?

预期结果

我希望由于数据已存储在设备上,并且无法检测到互联网连接,因此它应该几乎立即返回数据。

代码

同步课程

GetPolicies() 方法是发生延迟的地方。 这是其中一个组件的示例。每个其他组件的格式相同,但数据不同。

    IMobileServiceSyncTable<policy_procedure> policyTable = SyncController.policyTable;

    public async Task<List<policy_procedure>> GetPolicies(string companyId)
    {
        //SemaphoreSlim
        await SyncController.dbOperation.WaitAsync();
        try
        {
            await SyncController.Initialize();
            await policyTable.PullAsync("policy_procedure", policyTable.Where(p => p.fk_company_id == companyId).Where(p=> p.signature!=null || p.signature!=""));
            return await policyTable.ToListAsync();
        }
        catch (Exception ex)
        {
            //For some reason, when this method is called and the device is offline, it will fall into this catch block. 
            //I assume this is standard for offline sync, as it's trying to do a pull with no connection, causing it to fail. 
            //Through using breakpoints, the delay occurs even before it reaches this catch statement.
            Console.WriteLine(ex);
            return await policyTable.ToListAsync();
        }
        finally
        {
            SyncController.dbOperation.Release();
        }
    }

同步控制器

    public static SemaphoreSlim dbOperation = new SemaphoreSlim(1, 1);
    public static MobileServiceClient client;
    public static MobileServiceSQLiteStore store;
    public static async Task Initialize()
    {
        try
        {
            //This line is not standard for Offline Sync.
            //The plugin returns true or false for the devices current connectivity. 
            //It's my attempt to see if there is a connection, to eliminate the load time.
            //This does immediately take it back to the try statement in GetPolicies
            if (!CrossConnectivity.Current.IsConnected)
                return;
            if (client ? .SyncContext ? .IsInitialized ? ? false)
                return;
            client = new MobileServiceClient(AppSettings.azureUrl);
            var path = "local.db"; //Normally uses company ID, 
            path = Path.Combine(MobileServiceClient.DefaultDatabasePath, path);
            store = new MobileServiceSQLiteStore(path);
            /************************/
            #
            region Table Definitions in local SQLite DB
            //Define all the tables in the sqlite db
            ..
            store.DefineTable < policy_procedure > ();
                ..#endregion
            await client.SyncContext.InitializeAsync(store);
            /************/
            #
            region Offline Sync Tables
                ..
            policyTable = client.GetSyncTable < policy_procedure > ();
                ..#endregion
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex)
        }
    }

我尝试过什么

好吧,我不太确定是什么造成了这种情况,因此我的大部分尝试都是在此等待时间发生之前强制异常,因此它可能会超出GetPolicies try-catch,因为等待时间似乎在PullAsync上。

我最近的尝试在上面的代码(SyncController)中得到了评论,我使用James Montemagno的Connectivity Plugin来检测手机的网络连接。 (我已经单独测试了这个,这可以毫不拖延地正常工作。)

1 个答案:

答案 0 :(得分:1)

简短的说法是,如果您的设备处于离线状态,则不希望在GetPolicies方法中调用PullAsync。例如,你可以做

    try
    {
        await SyncController.Initialize();
        if (CrossConnectivity.Current.IsConnected)
        {
            await policyTable.PullAsync("policy_procedure", policyTable.Where(p => p.fk_company_id == companyId).Where(p=> p.signature!=null || p.signature!=""));
        }
        return await policyTable.ToListAsync();
    }

但你也想要处理这是第一次运行应用程序的情况,因此你还没有任何记录。