也许我错过了一些东西但是我在Realm同时读取和写入时得到了一些奇怪的结果。
我第一次在一个更大的项目中遇到过这个问题,但现在只需要在测试项目中重现它。
场景:创建一个带有两个RealmObject
字段的DateTimeOffset
对象,然后每分钟更新一次。另一个线程每10秒读取一次并输出值。
我首先会显示输出,因为它最相关。 paranthesis中的时间是记录输出的时间。其余的是标识符(READER / WRITER),然后是RealmObject
的JSON表示。
成功写入后,读者会读取旧值一段时间,然后读取新值,然后再次读取旧值。如果我重新启动应用程序,那么一切都很好,当然,有一段时间了。
//读者开始阅读。输出正确
[0:](10:05:44.656)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}] [0:](10:05:54.656)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}] [0:](10:06:04.657)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}]
// Writer进来并更新值。
[0:](10:06:07.523)作者: {" LastSyncTime":" 2016-07-17T22:06:07.521 + 00:00"" LastChangeDate":" 2016-07-17T22: 11:07.523 + 00:00"" IsManaged":真}
//读者暂时读取不正确的(OLD)值
[0:](10:06:14.661)读者:> [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}] [0:](10:06:24.678)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}] [0:](10:06:34.678)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}]
// Reader suddnely读取正确的值
[0:](10:06:44.678)读者: [{" LastSyncTime":" 2016-07-17T22:06:07.521 + 00:00"" LastChangeDate":" 2016-07-17T22 :11:07.523 + 00:00"" IsManaged":真}]
//阅读器回退到之前的值(????)
[0:](10:06:54.678)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}] [0:](10:07:04.678)读者: [{" LastSyncTime":" 2016-07-17T22:04:45.384 + 00:00"" LastChangeDate":" 2016-07-17T22 :09:45.384 + 00:00"" IsManaged":真}]
代码:
public class TimestampDataObject : RealmObject
{
public DateTimeOffset LastSyncTime { get; set; }
public DateTimeOffset? LastChangeDate { get; set; }
}
写作部分:
Observable.Interval(TimeSpan.FromMinutes(1)).Subscribe(async (v) =>
{
await Realm.GetInstance().WriteAsync(r =>
{
var item = r.All<TimestampDataObject>().AsEnumerable().FirstOrDefault();
if (item == null)
{
item = r.CreateObject<TimestampDataObject>();
}
item.LastSyncTime = DateTimeOffset.UtcNow;
item.LastChangeDate = DateTimeOffset.UtcNow.AddMinutes(5);
Debug.WriteLine($"({DateTime.UtcNow.ToString("hh:mm:ss.fff")}) WRITER: {JsonConvert.SerializeObject(item)}");
});
});
读者:
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(v =>
{
var latestTimestampInfo = Realm.GetInstance().All<TimestampDataObject>();
Debug.WriteLine($"({ DateTime.UtcNow.ToString("hh:mm:ss.fff")}) READER: {JsonConvert.SerializeObject(latestTimestampInfo)}");
});
不确定会发生什么。也许一些Realm家伙可以澄清这一点。
更新
当读者和作者在同一个Thread
上时,做了一些更多的测试,显然一切正常。在日志中添加了时间戳之后的托管线程ID。因此,在下面你可以看到在线程11上运行的读者 - 与作者的相同 - 如何正常工作。但是,在不同线程上运行的读取器会输出旧值:
//更新前(正确)
[0:](10:56:53.679,11)读者: [{&#34; LastSyncTime&#34;:&#34; 2016-07-17T22:55:55.573 + 00:00&#34;&#34; LastChangeDate&#34;:&#34; 2016-07-17T23 :00:55.576 + 00:00&#34;&#34; IsManaged&#34;:真}]
//更新在第11个主题上完成
[0:](10:56:55.552,11)作者: {&#34; LastSyncTime&#34;:&#34; 2016-07-17T22:56:55.552 + 00:00&#34;&#34; LastChangeDate&#34;:&#34; 2016-07-17T23: 01:55.553 + 00:00&#34;&#34; IsManaged&#34;:真}
//线程11上的阅读器输出正确的值
[0:](10:57:03.702,11)读者: [{&#34; LastSyncTime&#34;:&#34; 2016-07-17T22:56:55.552 + 00:00&#34;&#34; LastChangeDate&#34;:&#34; 2016-07-17T23 :01:55.553 + 00:00&#34;&#34; IsManaged&#34;:真}]
//再次,读者在线程11上。正确输出。
[0:](10:57:13.702,11)读者: [{&#34; LastSyncTime&#34;:&#34; 2016-07-17T22:56:55.552 + 00:00&#34;&#34; LastChangeDate&#34;:&#34; 2016-07-17T23 :01:55.553 + 00:00&#34;&#34; IsManaged&#34;:真}]
//线程12上的读者输出错误结果
[0:](10:57:23.703,12)读者: [{&#34; LastSyncTime&#34;:&#34; 2016-07-17T22:23:19.674 + 00:00&#34;&#34; LastChangeDate&#34;:&#34; 2016-07-17T22 :28:19.676 + 00:00&#34;&#34; IsManaged&#34;:真}]
//再次,读者在线程11上。正确输出。
[0:](10:57:33.703,11)读者: [{&#34; LastSyncTime&#34;:&#34; 2016-07-17T22:56:55.552 + 00:00&#34;&#34; LastChangeDate&#34;:&#34; 2016-07-17T23 :01:55.553 + 00:00&#34;&#34; IsManaged&#34;:真}]
答案 0 :(得分:1)
没关系。我似乎需要为没有事件循环的线程上创建和使用的Realm.Refresh()
实例调用Realm
。否则,它们在创建时保持与写提交同步。
Realm.Refresh()
使域进入最新的写提交并将其用于后续读取。
当您最初在某个线程上打开一个Realm时,它的状态将基于 关闭最近成功的写入提交,它将保持打开状态 该版本直到刷新。领域会自动刷新 每次runloop迭代的开始。如果一个线程没有runloop (然后,通常是后台线程中的情况) 必须手动调用Realm.Refresh()才能推进 交易到最近的状态。
读者部分现在看起来像这样:
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(v =>
{
var realm = Realm.GetInstance();
realm.Refresh();
var latestTimestampInfo = realm.All<TimestampDataObject>();
Debug.WriteLine($"({ DateTime.UtcNow.ToString("hh:mm:ss.fff")},{Thread.CurrentThread.ManagedThreadId}) READER: {JsonConvert.SerializeObject(latestTimestampInfo)}");
});