我正在使用Realm和Xamarin Forms项目,我已经阅读过如何跨线程共享域实体实例。
给出以下代码,使用在第100行获得的route
,然后在awaited
调用104后再次在第109行访问,危险吗?
我是使用Realm的新手,但是如果这是真的,那么必须在任何/每个awaited
调用之后获得Realm的新实例和任何正在使用的对象。似乎繁重......
正在使用在100号线获得的路线,然后在等待104的呼叫后再次在109号线上访问,危险吗?
是的,在下一个foreach迭代中,您将最终得到一个不同的托管线程,并且Realm将抛出不同的线程访问异常。
关键是使用SynchronizationContext
,所以你的等待延续是在同一个线程上(当然,因为你将在不同的线程中,跳过使用基于Realm的异步方法)
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的事实......我在绝大多数项目中使用它。