2016-04-14 20 views
0

私は現在、ストリームからデータを逆シリアル化するために同様のコードを使用しています。JSON.NETストリームの逆シリアル化をキャンセルします。

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

このプロセスは、巨大なjsonファイルや接続が遅くなることがあるため、ユーザーによる開始デシリアライズのキャンセルをサポートできますか?

+0

私はあなたがしたいことを理解しています。 1つのスレッドで実行している場合、どのようにユーザーはキャンセルできますか?複数のスレッド(.Net 3.5)で実行している場合は、['BackgroundWorker'](https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v = vs90))を使用してください。 aspx)? https://msdn.microsoft.com/en-us/library/ywkkz4s1%28v=vs.100%29.aspxも参照してください。 – dbc

答えて

1

JsonTextReaderは、箱から出して、これをサポートしていませんが、あなたが読者をサブクラス化することができるようにJson.NETは正しく、低レベルのコードから来る(すなわち再スロー)の例外を処理しますし、

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) 
    { 
    } 
} 

をし、それが好きで使用します:それを自分で行う

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

その後、高いコード・レベルで、JsonReaderCancelledException例外をキャッチ。

checkCancelledメソッドが別のスレッドで設定されているboolフラグをチェックしている場合は、volatileと宣言する必要があります。 Is it safe to use a boolean flag to stop a thread from running in C#を参照してください。

私はこれを実稼働させる前にパフォーマンスをテストしたいと思っています。 checkCancelledの代理人をすべての読み込みに呼び出すのが実行できない場合は、10回または100回の読み込みごとに実行できます。

0

あなたのシリアライザは、キャンセルをサポートしていない場合は、代わりに次の操作を行うことができます。データ

例えばをフェッチ上層に

  • 支援キャンセルをWebClientのために1がWebClient.CancelAsyncなどを活用するでしょう...

関連する問題