C#异步调用和领域实例

时间:2019-03-07 23:22:20

标签: xamarin xamarin.forms realm realm-mobile-platform

我正在将Realm与Xamarin Forms项目一起使用,并且已经阅读了有关如何无法跨线程共享Realm实体实例的信息。

给出以下代码,使用的是在第100行中获得的route,然后在对104进行awaited调用之后在109行再次访问,这很危险吗?

我对使用Realm并不陌生,但是如果是这样,那么在每次awaited调用之后,必须获得Realm的新实例以及正在使用的任何对象。似乎很麻烦...

enter image description here

1 个答案:

答案 0 :(得分:3)

  

使用的是在第100行中获得的路由,然后在104上等待的呼叫之后再次访问第109行,这很危险吗?

是的,在下一个foreach迭代中,您将最终获得一个不同的托管线程,而Realm将引发另一个线程访问异常。

关键是使用SynchronizationContext,以便您的等待继续在同一线程上(当然,由于您将在不同的线程中,因此请跳过基于Realm的异步方法的使用)< / p>

使用Stephen Cleary的Nito.AsyncEx(他是同步上下文之王)

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);
    }
});

使用SushiHangover.RealmThread

不久前,我为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的...我在绝大多数项目中都使用它。