将反序列化方法转换为异步

时间:2012-08-09 12:54:18

标签: c# serialization asynchronous

我正在尝试将使用Async / Await反序列化对象的方法转换为字符串。

    public static T DeserializeObject<T>(string xml)
    {
        using (StringReader reader = new StringReader(xml))
        {
            using (XmlReader xmlReader = XmlReader.Create(reader))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(T));
                T theObject = (T)serializer.ReadObject(xmlReader);
                return theObject;
            }
        }
    }

4 个答案:

答案 0 :(得分:14)

大多数序列化API没有async实现,这意味着你唯一能做的就是 wrap 一个同步方法。例如:

public static Task<T> DeserializeObjectAsync<T>(string xml)
{
    using (StringReader reader = new StringReader(xml))
    {
        using (XmlReader xmlReader = XmlReader.Create(reader))
        {
            DataContractSerializer serializer =
                new DataContractSerializer(typeof(T));
            T theObject = (T)serializer.ReadObject(xmlReader);
            return Task.FromResult(theObject);
        }
    }
}

这不是实际异步 - 它只是满足所需的API。如果您有选项,在结果可能经常是同步/

的情况下,最好使用ValueTask<T>

无论哪种方式,您都应该能够执行以下操作:

var obj = await DeserializeObject<YourType>(someXml);
Debug.WriteLine(obj.Name); // etc

无需知道实际实现是同步还是异步。

答案 1 :(得分:1)

一个小样本,非常原始的方式:

    public delegate T Async<T>(string xml);

    public void Start<T>()
    {
        string xml = "<Person/>";
        Async<T> asyncDeserialization = DeserializeObject<T>;
        asyncDeserialization.BeginInvoke(xml, Callback<T>, asyncDeserialization);
    }

    private void Callback<T>(IAsyncResult ar)
    {
        Async<T> dlg = (Async<T>)ar.AsyncState;
        T item = dlg.EndInvoke(ar);
    }

    public T DeserializeObject<T>(string xml)
    {
        using (StringReader reader = new StringReader(xml))
        {
            using (XmlReader xmlReader = XmlReader.Create(reader))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(T));
                T theObject = (T)serializer.ReadObject(xmlReader);
                return theObject;
            }
        }
    }

定义一个委托并使用它来回调/使用回调调用。

使用下一版本的C#,您可以使用async关键字来异步运行代码。

答案 2 :(得分:0)

当您使用string作为数据源时,执行异步操作只会带来更多开销,并且不会为您提供任何内容。

但是如果您从流中读取数据,则可以从源流复制到MemoryStream(缓冲所有数据),然后从MemoryStream反序列化,这将增加内存使用量但会降低你将阻止线程的时间。

答案 3 :(得分:-2)

您可以返回

Task.FromResult(theObject)