Xamarin 与 AzureMobileServices 离线同步:初始离线加载非常慢
Xamarin Offline Sync with AzureMobileServices: Initial offline load incredibly slow
我成功地使用 Azure 移动服务和 Xamarin Forms 在 Azure 托管的 SQL 数据库上执行 CRUD 操作。离线同步部分将数据存储在 phone 上的 SQLite 数据库中。在让它像我们现在这样顺利地工作的过程中遇到了一些颠簸,但这仍然是最后一个障碍。
问题
当设备没有连接时(在各种物理和模拟设备上使用飞行模式进行测试)- 第一次访问任何离线数据时,需要 非常 很长时间 return 任何事情。如果数据存在于 SQLite DB 中,则属于这种情况。
没有抛出任何异常,也没有任何我能看到的打印到日志中的信息表明延迟可能是什么。
举个例子,20 行的 PullAsync()
在线时可能需要 5 秒,并且该数据存储在 SQLite 数据库中。将设备置于离线模式后,相同的操作最多可能需要 60 秒。这些数字是相当随意的,但延迟明显太长了。
除此之外,这种长时间加载仅在 第一次 调用任何离线同步方法时发生。在那之后,每个方法都接近即时,正如我所期望的那样——但为什么不是第一次呢?
预期结果
我希望因为数据已经存储在设备上,并且无法检测到互联网连接,所以它应该 return 数据几乎是即时的。
代码
同步Class
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-赶上,因为等待时间似乎在 PullAsync 上。
我最近对此的尝试在上面的代码 (SyncController
) 中进行了注释,其中我使用 James Montemagno 的 Connectivity Plugin 来检测 phone 的网络连接。 (我已经单独测试过了,可以正常工作,没有延迟。)
简而言之,如果您的设备处于离线状态,您不想在 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();
}
但您还需要处理应用首次运行的情况,因此您还没有任何记录。
我成功地使用 Azure 移动服务和 Xamarin Forms 在 Azure 托管的 SQL 数据库上执行 CRUD 操作。离线同步部分将数据存储在 phone 上的 SQLite 数据库中。在让它像我们现在这样顺利地工作的过程中遇到了一些颠簸,但这仍然是最后一个障碍。
问题
当设备没有连接时(在各种物理和模拟设备上使用飞行模式进行测试)- 第一次访问任何离线数据时,需要 非常 很长时间 return 任何事情。如果数据存在于 SQLite DB 中,则属于这种情况。
没有抛出任何异常,也没有任何我能看到的打印到日志中的信息表明延迟可能是什么。
举个例子,20 行的 PullAsync()
在线时可能需要 5 秒,并且该数据存储在 SQLite 数据库中。将设备置于离线模式后,相同的操作最多可能需要 60 秒。这些数字是相当随意的,但延迟明显太长了。
除此之外,这种长时间加载仅在 第一次 调用任何离线同步方法时发生。在那之后,每个方法都接近即时,正如我所期望的那样——但为什么不是第一次呢?
预期结果
我希望因为数据已经存储在设备上,并且无法检测到互联网连接,所以它应该 return 数据几乎是即时的。
代码
同步Class
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-赶上,因为等待时间似乎在 PullAsync 上。
我最近对此的尝试在上面的代码 (SyncController
) 中进行了注释,其中我使用 James Montemagno 的 Connectivity Plugin 来检测 phone 的网络连接。 (我已经单独测试过了,可以正常工作,没有延迟。)
简而言之,如果您的设备处于离线状态,您不想在 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();
}
但您还需要处理应用首次运行的情况,因此您还没有任何记录。