2016-07-17 5 views
1

Vielleicht etwas aus mir fehlt, aber ich einige seltsame Ergebnisse, die beim Lesen und parallel von Realm, gleiche Objekt zu schreiben.inkonsistente Ergebnisse mit parallel liest und schreibt in Realm

begegnete ich zuerst diese in einem größeren Projekt, aber jetzt gerade geschaffen es in einem Testprojekt zu reproduzieren.

Szenario: Ein RealmObject Objekt mit zwei Felder wird erstellt und dann jede Minute aktualisiert. Ein anderer Thread liest alle 10 Sekunden und gibt die Werte aus.

Ich werde zuerst die Ausgabe zeigen, da es am relevantesten ist. Die Zeit in der Paranthese ist der Zeitpunkt, zu dem die Ausgabe protokolliert wird. Der Rest ist die Kennung (READER/WRITER) und dann die JSON-Darstellung der RealmObject.

Was passiert, ist, dass nach einem erfolgreichen Schreib, der Leser die alten Werte für eine Weile liest, liest dann den neuen Wert und liest dann die alten wieder Werte. Wenn ich die App neu starte, ist natürlich alles für eine Weile OK.

// Der Leser beginnt zu lesen. Der Ausgang ist korrekt

[0:] (10: 05: 44,656) READER: [{ "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) READER: [{ "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) LESER: [{"LastSyncTime": "2016-07-17T22: 04: 45.384 + 00: 00", "LastChangeDate": "2016-07-17T22: 09: 45.384 + 00: 00", "IsManaged": true}]

// Writer kommt und aktualisiert die Werte.

[0:] (10: 06: 07.523) Verfasser: { "LastSyncTime": "2016-07-17T22: 06: 07.521 + 00: 00", "LastChangeDate": "2016-07-17T22 11:: 07.523 + 00: 00" , "IsManaged": true}

// Reader liest falsch (OLD) Werte für eine Weile

[0:] (10: 06: 14,661) READER :> [{"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) READER: [{"" 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) LESER: [{" LastSyncTime ":" 2016-07-17T22: 04: 45.384 + 00: 00 “, "LastChangeDate": "2016-07-17T22: 09: 45,384 + 00: 00", "IsManaged": true}]

// Reader suddnely korrekte Werte

[0 lautet:] (10: 06: 44.678) LESER: [{"LastSyncTime": "2016-07-17T22: 06: 07.521 + 00: 00", "LastChangeDate": "2016-07-17T22: 11: 07.523 + 00: 00 "," IsManaged ": true}]

// Leser fällt auf vorherige Werte zurück (????)

[0:] (10: 06: 54,678) READER: [{ "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) LESER: [{" LastSyncTime ":" 2016-07-17T22: 04: 45.384 + 00: 00 " "LastChangeDate": "2016-07-17T22: 09: 45,384 + 00: 00", "IsManaged": true}]

der Code:

public class TimestampDataObject : RealmObject 
{ 
    public DateTimeOffset LastSyncTime { get; set; } 
    public DateTimeOffset? LastChangeDate { get; set; } 
} 

Der Schreibteil:

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

Der Leser:

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

Nicht sicher, was passiert. Vielleicht können einige der Realm-Jungs das klären.

UPDATE

Hat einige weitere Tests und scheinbar alles funktioniert gut, wenn der Leser und Schreiber auf dem gleichen Thread sind. In den Protokollen wurde die ID des verwalteten Threads direkt nach den Zeitstempeln hinzugefügt. So können Sie unten sehen, wie ein Leser, der auf Thread 11 läuft - genauso wie der des Verfassers - gut funktioniert. Aber ein Leser auf einem anderen Thread ausgeführt gibt die alten Werte:

// Vor dem Update (korrekt)

[0:] (10: 56: 53.679,11) READER: [ {"LastSyncTime": "2016-07-17T22: 55: 55.573 + 00: 00", "LastChangeDate": "2016-07-17T23: 00: 55.576 + 00: 00", "IsManaged": Wahr}]

// Die Aktualisierung wird auf Faden 11 getan

[0:] (10: 56: 55.552,11) W RITER: {"LastSyncTime": "2016-07-17T22: 56: 55.552 + 00: 00", "LastChangeDate": "2016-07-17T23: 01: 55.553 + 00: 00", "IsManaged": true}

// Reader auf Faden 11

korrekte Werte Ausgänge [0:] (10: 57: 03.702,11) READER: [{ "LastSyncTime": "2016-07-17T22: 56: 55.552 + 00: 00 "," LastChangeDate ":" 2016-07-17T23: 01: 55.553 + 00: 00 "," IsManaged ": true}]

// Auch hier ist der Leser auf Thread 11. Korrekte Ausgabe

[0:] (10: 57: 13.702,11) READER: [{ "LastSyncTime": "2016-07-17T22: 56: 55,552 + 00: 00", "LastChangeDate": "2016- 07-17T23: 01: 55,553 + 00: 00" , "IsManaged": true}]

// Ein Leser auf Faden 12 gibt falsche Ergebnisse

[0:] (10: 57: 23,703 , 12) READER: [{"LastSyncTime": "2016-07-17T22: 23: 19.674 + 00: 00", "LastChangeDate": "2016-07-17T22: 28: 19.676 + 00: 00", "IsManaged ": Wahr}]

// Auch hier ist der Leser auf Thread 11. Richtige Ausgabe.

[0:] (10: 57: 33.703,11) READER: [{ "LastSyncTime": "2016-07-17T22: 56: 55.552 + 00: 00" , "LastChangeDate": "2016-07-17T23: 01: 55,553 + 00: 00", "IsManaged". True}]

Antwort

1

Nevermind Es scheint, ich brauche Realm.Refresh() zu verlangen Realm Instanzen erstellt und auf Threads ohne Ereignisschleife verwendet. Sonst bleiben sie synchron mit dem Schreib an dem Punkt begehen, wenn sie erstellt wurden.

Realm.Refresh() das Reich auf die neueste Schreib vorzurücken verursacht commit und verwendet für nachfolgende liest .

Relevant documentation:

Wenn Sie zunächst einen Realm für einen Thread öffnen, basiert sein Status auf dem letzten erfolgreichen Schreib-Commit, und er verbleibt auf diese Version, bis er aktualisiert wird. Realms werden automatisch bei beim Start jeder Runloop-Iteration aktualisiert. Wenn ein Thread keinen Runloop hat (was normalerweise in einem Hintergrundthread der Fall ist), muss Realm.Refresh() manuell aufgerufen werden, um die -Transaktion auf den neuesten Stand zu bringen.

Der Leser Teil wie folgt aussieht jetzt:

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)}"); 
}); 
+0

Vielen Dank für den Tech-Support Zeitersparnis! Ja, wo es einen Runloop gibt, benutzen wir das, was sonst erfrischend ist ** deine ** Verantwortung. Gute Frage zu stellen, obwohl! –

+0

@AndyDent: Danke! Ich habe mich gefragt ... Gab es einen Design-/Entscheidungsgrund, einen Aufruf von 'Refresh' in' GetInstance' nicht zu umbrechen? –

Verwandte Themen