我目前正在使用类似的代码对流中的数据进行反序列化。
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)
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次读取就可以执行此操作。
答案 1 :(得分:0)