C # асинхронные вызовы и экземпляры областей - PullRequest
0 голосов
/ 08 марта 2019

Я использую Realm с проектом Xamarin Forms, и я прочитал о том, как экземпляры сущностей области не могут совместно использоваться потоками.

Учитывая следующий код, используется route, полученный в строке100, а затем снова вызван на линии 109 после вызова awaited на 104, опасно?

Я новичок в использовании Realm, но если это правда, то нужно получить новый экземпляр Realm и любой объект, с которым работали после любого / каждого awaited вызова.Кажется обременительным ...

enter image description here

1 Ответ

3 голосов
/ 08 марта 2019

использует маршрут, полученный в строке 100, а затем снова доступен по строке 109 после ожидаемого вызова на 104, опасно?

Да, на следующей итерации foreach вы получите другой управляемый поток, а Realm сгенерирует другое исключение доступа к потоку.

Ключ в том, чтобы использовать SynchronizationContext, чтобы ваши ожидающие продолжения находились в одном потоке (и, конечно, поскольку вы будете в другом потоке, пропустите использование асинхронных методов на основе Царства)

Использование Nito.AsyncEx Стивена Клири (он король контекстов синхронизации ?)

re: как я могу принудительно ожидать завершения в том же потоке?

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

Я недавно написал simple SynchronizationContext для Realm, он работает для моих нужд и имеет специальный API для Realm.

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 в качестве универсального решения, которое хорошо поддерживается и в связи с тем, что это от Стивена Клири .. Я использую его в подавляющем большинстве своих проектов.

...