标签:c sqlite xamarin-ios xamarin sqlite-net-2
我们使用以下内容:
> Xamarin 3(Xamarin表格)
> MonoTouch
> sqlite.net
> iOS模拟器/硬件
该应用程序与后台线程上的服务器同步数据.整个应用程序只共享一个SQLite连接对象.前台查询在后台同步运行的同时执行.所有这些在应用程序的Windows 8.1版本上都可以正常工作(即在MSFT Surface和类似版本上).然而,一旦我们切换到Xamarin / mono,我们开始不断崩溃,如下所示.
研究导致了这篇文章:http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/
他正在使用Mono.Data.SqliteClient,而不是像我们一样使用sqlite.net.
他的解决方案涉及显式处理Command对象以确保GC可以保持等等.当我尝试将我的Command对象(来自sqlite.net)包装在using(){}子句中时,我发现它们不是一次性的.
我尝试插入100毫秒延迟并停止崩溃,但对我们来说这不是一个可行的解决方案.
这里对sqlite.net有什么希望,还是应该寻找一种不同的方式来使用sqlite?
mono-rt: Stacktrace:
mono-rt: at <unknown> <0xffffffff>
mono-rt: at (wrapper managed-to-native) SQLite.SQLite3.Prepare2 (intptr,string,int,intptr&,intptr) <IL 0x0003c, 0xffffffff>
...
mono-rt:
Native stacktrace:
mono-rt:
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
解决方法:
当我尝试从多个线程敲击相同的sqlite.net连接时,我很确定我得到了有意义的错误而不是SIGSEGV,但是如果你认为那是罪魁祸首,解决方案很简单:你需要限制对任何sqlite的访问.将数据库一次触摸到一个线程的网络方法.
在您在应用程序中共享单个SQLiteConnection实例的场景中(这是一种非常有效的处理方式),我建议创建一个简化的代理类来包装您的sqlite.net连接,只公开您想要的方法并保护访问具有锁定语句的那些,即:
public class DatabaseWrapper : IDisposable
{
// Fields.
private readonly SQLiteConnection Connection;
private readonly object Lock = new object();
public DatabaseWrapper(string databasePath)
{
if (string.IsNullOrEmpty(databasePath)) throw new ArgumentException("Database path cannot be null or empty.");
this.Connection = new SQLiteConnection(databasePath);
}
public IEnumerable<T> Entities<T>() where T : new()
{
lock (this.Lock)
{
return this.Connection.Table<T>();
}
}
public IEnumerable<T> Query<T>(string query, params object[] args) where T : new()
{
lock (this.Lock)
{
return this.Connection.Query<T>(query, args);
}
}
public int ExecuteNonQuery(string sql, params object[] args)
{
lock (this.Lock)
{
return this.Connection.Execute(sql, args);
}
}
public T ExecuteScalar<T>(string sql, params object[] args)
{
lock (this.Lock)
{
return this.Connection.ExecuteScalar<T>(sql, args);
}
}
public void Insert<T>(T entity)
{
lock (this.Lock)
{
this.Connection.Insert(entity);
}
}
public void Update<T>(T entity)
{
lock (this.Lock)
{
this.Connection.Update(entity);
}
}
public void Upsert<T>(T entity)
{
lock (this.Lock)
{
var rowCount = this.Connection.Update(entity);
if (rowCount == 0)
{
this.Connection.Insert(entity);
}
}
}
public void Delete<T>(T entity)
{
lock (this.Lock)
{
this.Connection.Delete(entity);
}
}
public void Dispose()
{
this.Connection.Dispose();
}
}
附:显然,因为你在多个线程上做事,你需要非常小心不要引入竞争条件,这就是为什么,例如,我包含了保证以原子方式执行两步“更新或插入”操作的Upsert方法.
标签:c,sqlite,xamarin-ios,xamarin,sqlite-net-2 来源: https://codeday.me/bug/20190624/1278259.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。