【发布时间】:2016-07-17 22:23:39
【问题描述】:
也许我遗漏了一些东西,但我在从 Realm 并行读取和写入时得到了一些奇怪的结果,同一个对象。
我第一次遇到这个是在一个更大的项目中,但现在才设法在一个测试项目中重现它。
场景:创建一个带有两个DateTimeOffset 字段的RealmObject 对象,然后每分钟更新一次。另一个线程每 10 秒读取一次并输出值。
我将首先显示输出,因为它最相关。括号中的时间是记录输出的时间。剩下的是标识符 (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":true}] [0:] (10:05:54.656) 读者: [{"LastSyncTime":"2016-07-17T22:04:45.384+00:00","LastChangeDate":"2016-07-17T22:09:45.384+00:00","IsManaged":true}] [0:] (10:06:04.657) 读者: [{"LastSyncTime":"2016-07-17T22:04:45.384+00:00","LastChangeDate":"2016-07-17T22:09:45.384+00:00","IsManaged":true}]
//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":true}
//Reader 读取不正确(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":true}] [0:] (10:06:24.678) 读者: [{"LastSyncTime":"2016-07-17T22:04:45.384+00:00","LastChangeDate":"2016-07-17T22:09:45.384+00:00","IsManaged":true}] [0:] (10:06:34.678) 读者: [{"LastSyncTime":"2016-07-17T22:04:45.384+00:00","LastChangeDate":"2016-07-17T22:09:45.384+00:00","IsManaged":true}]
//阅读器突然读取到正确的值
[0:] (10:06:44.678) 读者: [{"LastSyncTime":"2016-07-17T22:06:07.521+00:00","LastChangeDate":"2016-07-17T22:11:07.523+00:00","IsManaged":true}]
//Reader 回退到以前的值 (????)
[0:] (10:06:54.678) 读者: [{"LastSyncTime":"2016-07-17T22:04:45.384+00:00","LastChangeDate":"2016-07-17T22:09:45.384+00:00","IsManaged":true}] [0:] (10:07:04.678) 读者: [{"LastSyncTime":"2016-07-17T22:04:45.384+00:00","LastChangeDate":"2016-07-17T22:09:45.384+00:00","IsManaged":true}]
代码:
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) 读者: [{"LastSyncTime":"2016-07-17T22:55:55.573+00:00","LastChangeDate":"2016-07-17T23:00:55.576+00:00","IsManaged":true}]
//更新在线程11完成
[0:] (10:56:55.552,11) 作者: {"LastSyncTime":"2016-07-17T22:56:55.552+00:00","LastChangeDate":"2016-07-17T23:01:55.553+00:00","IsManaged":true}
//线程11上的Reader输出正确的值
[0:] (10:57:03.702,11) 读者: [{"LastSyncTime":"2016-07-17T22:56:55.552+00:00","LastChangeDate":"2016-07-17T23:01:55.553+00:00","IsManaged":true}]
//同样,阅读器在线程 11 上。正确输出。
[0:] (10:57:13.702,11) 读者: [{"LastSyncTime":"2016-07-17T22:56:55.552+00:00","LastChangeDate":"2016-07-17T23:01:55.553+00:00","IsManaged":true}]
//线程 12 上的阅读器输出错误结果
[0:] (10:57:23.703,12) 读者: [{"LastSyncTime":"2016-07-17T22:23:19.674+00:00","LastChangeDate":"2016-07-17T22:28:19.676+00:00","IsManaged":true}]
//同样,阅读器在线程 11 上。正确输出。
[0:] (10:57:33.703,11) 读者: [{"LastSyncTime":"2016-07-17T22:56:55.552+00:00","LastChangeDate":"2016-07-17T23:01:55.553+00:00","IsManaged":true}]
【问题讨论】:
标签: c# xamarin realm realm-net