is using the route obtained in line 100, and then accessed again on line 109 after the awaited call on 104, dangerous?
Yes, on the next foreach iteration, you will end up with a different managed thread, and Realm will throw an different thread access exception.
The key is to use a SynchronizationContext
so your await continuations are on the same thread (and, of course, since you will be in a different thread, skip the use of the Realm-based async methods)
Using Stephen Cleary's Nito.AsyncEx (he is the king of sync contexts )
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);
}
});
Using SushiHangover.RealmThread
I wrote a simple SynchronizationContext for Realm awhile back, it works for my needs and has a specialized API for 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);
}
});
}
Note: For someone that does not understand SynchronizationContext
well, I would highly recommend using Nito.AsyncEx
as a generic solution that is well supported and due to the fact that is from Stephen Cleary... I use it in a vast majority of my projects.