2016-04-14 18 views
0

Ich verwende derzeit ähnlichen Code zum Deserialisieren von Daten aus dem Stream.Abbrechen JSON.NET Stream Deserialisierung

public static MyClass Parse(Stream stream) 
    { 
     var serializer = new JsonSerializer(); 
     using (var sr = new StreamReader(stream)) 
     using (var jsonTextReader = new JsonTextReader(sr)) 
     { 
      var result = serializer.Deserialize<MyClass>(jsonTextReader); 
      return result; 
     } 
    } 

Ist es möglich, das Abbrechen gestartet Deserialisierung durch den Benutzer zu unterstützen, da dieser Prozess eine lange für große json Dateien und langsame Verbindung nehmen können?

+0

Nicht ganz sicher, ich verstehe, was Sie tun möchten. Wenn Sie mit einem einzelnen Thread arbeiten, wie kann der Benutzer abbrechen? Wenn Sie mit mehreren Threads (in .Net 3.5) arbeiten, verwenden Sie bitte einen ['BackgroundWorker'' (https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker (v = vs.90). aspx)? Siehe auch https://msdn.microsoft.com/en-us/library/ywkkz4s1%28v=vs.100%29.aspx – dbc

Antwort

1

JsonTextReader dies aus der Box nicht unterstützt, aber Json.NET nicht korrekt verarbeiten (dh rethrow) Ausnahmen von der unteren Ebene Code kommen, so dass Sie die Leser Unterklasse könnte und do it yourself:

public class CancellableJsonTextReader : JsonTextReader 
{ 
    protected Func<bool> CheckCancelled { get; set; } 

    public CancellableJsonTextReader(TextReader reader, Func<bool> checkCancelled) 
     : base(reader) 
    { 
     this.CheckCancelled = checkCancelled; 
    } 

    public bool IsCancelled { get; private set; } 

    public override bool Read() 
    { 
     DoCheckCancelled(); 
     return base.Read(); 
    } 

    public override bool? ReadAsBoolean() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsBoolean(); 
    } 

    public override byte[] ReadAsBytes() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsBytes(); 
    } 

    public override DateTime? ReadAsDateTime() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsDateTime(); 
    } 

    public override DateTimeOffset? ReadAsDateTimeOffset() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsDateTimeOffset(); 
    } 

    public override decimal? ReadAsDecimal() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsDecimal(); 
    } 

    public override double? ReadAsDouble() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsDouble(); 
    } 

    public override int? ReadAsInt32() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsInt32(); 
    } 

    public override string ReadAsString() 
    { 
     DoCheckCancelled(); 
     return base.ReadAsString(); 
    } 

    private void DoCheckCancelled() 
    { 
     if (!IsCancelled && CheckCancelled != null) 
      IsCancelled = CheckCancelled(); 
     if (IsCancelled) 
     { 
      throw new JsonReaderCancelledException(); 
     } 
    } 
} 

public class JsonReaderCancelledException : JsonReaderException 
{ 
    public JsonReaderCancelledException() { } 

    public JsonReaderCancelledException(string message) 
     : base(message) 
    { 
    } 

    public JsonReaderCancelledException(string message, Exception innerException) 
     : base(message, innerException) 
    { 
    } 

    public JsonReaderCancelledException(SerializationInfo info, StreamingContext context) 
     : base(info, context) 
    { 
    } 
} 

Und dann verwenden mag:

public static T Parse<T>(Stream stream, Func<bool> checkCancelled) 
    { 
     var serializer = new JsonSerializer(); 
     using (var sr = new StreamReader(stream)) 
     using (var jsonTextReader = new CancellableJsonTextReader(sr, checkCancelled)) 
     { 
      var result = serializer.Deserialize<T>(jsonTextReader); 
      return result; 
     } 
    } 

dann wird bei einer höheren Code-Ebene, die JsonReaderCancelledException Ausnahme fangen.

Wenn Ihre checkCancelled-Methode ein bool-Flag überprüft, das möglicherweise in einem anderen Thread festgelegt wird, müssen Sie es als volatile deklarieren. Siehe Is it safe to use a boolean flag to stop a thread from running in C#.

Sie möchten die Leistung testen, bevor Sie diese in Produktion nehmen. Wenn der checkCancelled Delegat für jeden Lesevorgang nicht performant ist, könnten Sie dies für alle 10 oder 100 Lesevorgänge tun.

0

Wenn Ihr Serializer nicht Stornierung nicht unterstützt, können Sie die folgende stattdessen tun:

  • Unterstützung Stornierung in der oberen Schicht, die die Daten

holt Z. B. für WebClient ein WebClient.CancelAsync nutzen würde, etc ...

Verwandte Themen