我正在将Realm与Xamarin Forms项目一起使用,并且已经阅读了有关如何无法跨线程共享Realm实体实例的信息。
给出以下代码,使用的是在第100行中获得的route
,然后在对104进行awaited
调用之后在109行再次访问,这很危险吗?
我对使用Realm并不陌生,但是如果是这样,那么在每次awaited
调用之后,必须获得Realm的新实例以及正在使用的任何对象。似乎很麻烦...
答案 0 :(得分:3)
使用的是在第100行中获得的路由,然后在104上等待的呼叫之后再次访问第109行,这很危险吗?
是的,在下一个foreach迭代中,您将最终获得一个不同的托管线程,而Realm将引发另一个线程访问异常。
关键是使用SynchronizationContext
,以便您的等待继续在同一线程上(当然,由于您将在不同的线程中,因此请跳过基于Realm的异步方法的使用)< / p>
re:how can i force await to continue on the same thread?
var yourRealmInstanceThread = new AsyncContextThread();
await yourRealmInstanceThread.Factory.Run(async () =>
{
var asyncExBasedRealm = Realm.GetInstance();
var routes = asyncExBasedRealm.All<UserModel>();
foreach (var route in routes)
{
// map it
// post it
await Task.Delay(TimeSpan.FromMilliseconds(1)); // Simulate some Task, i.e. a httpclient request....
// The following continuations will be executed on the proper thread
asyncExBasedRealm.Write(() => route.Uploaded = true);
}
});
不久前,我为Realm编写了 简单 的SynchronizationContext,它可以满足我的需要,并且具有针对Realm的专用API。
using (var realmThread = new RealmThread(realm.Config))
{
await realmThread.InvokeAsync(async myRealm =>
{
var routes = myRealm.All<UserModel>();
foreach (var route in routes)
{
// map it
// post it
await Task.Delay(TimeSpan.FromMilliseconds(1));
// The following continuations will be executed on the proper thread
myRealm.Write(() => route.Uploaded = true);
}
});
}
注意:对于不太了解SynchronizationContext
的人,我强烈建议使用Nito.AsyncEx
作为受到良好支持的通用解决方案,来自Stephen Cleary的...我在绝大多数项目中都使用它。