c# - 序列化 XAML 的 ConcurrentBag

标签 c# .net wpf xaml concurrency

在我的代码中,我有一个 ConcurrentBag<Point3DCollection> .

我正在尝试弄清楚如何序列化它们。当然,我可以遍历它或使用提供者模型类将其打包,但我想知道是否已经完成了。

Point3DCollection s 本身可能非常大,可以压缩以加快磁盘读写速度,但我为此所需的响应时间主要在用户界面范围内。换句话说,出于性能原因,我更喜欢二进制格式而不是 XAML 文本格式。 (有一个很好的 XAML 文本序列化器,它是 Helix 3D CodeProject 的一部分,但它比我想要的要慢。)

这是我要推出自己的序列化程序的用例,还是已经为此类数据打包的东西?

最佳答案

下面是一些处理 Point3DCollection 包的字符串和二进制序列化的扩展方法。正如我在评论中所说,我认为在所有情况下都没有最好的方法,因此您可能想同时尝试这两种方法。另请注意,他们使用 Stream 参数作为输入,因此您可以将这些与对 GZipStream 的调用链接起来。的 DeflateStream .

public static class Point3DExtensions
{
    public static void StringSerialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
    {
        if (bag == null)
            throw new ArgumentNullException("bag");

        if (stream == null)
            throw new ArgumentNullException("stream");

        StreamWriter writer = new StreamWriter(stream);
        Point3DCollectionConverter converter = new Point3DCollectionConverter();
        foreach (Point3DCollection coll in bag)
        {
            // we need to use the english locale as the converter needs that for parsing...
            string line = (string)converter.ConvertTo(null, CultureInfo.GetCultureInfo("en-US"), coll, typeof(string));
            writer.WriteLine(line);
        }
        writer.Flush();
    }

    public static void StringDeserialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
    {
        if (bag == null)
            throw new ArgumentNullException("bag");

        if (stream == null)
            throw new ArgumentNullException("stream");

        StreamReader reader = new StreamReader(stream);
        Point3DCollectionConverter converter = new Point3DCollectionConverter();
        do
        {
            string line = reader.ReadLine();
            if (line == null)
                break;

            bag.Add((Point3DCollection)converter.ConvertFrom(line));

            // NOTE: could also use this:
            //bag.Add(Point3DCollection.Parse(line));
        }
        while (true);
    }

    public static void BinarySerialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
    {
        if (bag == null)
            throw new ArgumentNullException("bag");

        if (stream == null)
            throw new ArgumentNullException("stream");

        BinaryWriter writer = new BinaryWriter(stream);
        writer.Write(bag.Count);
        foreach (Point3DCollection coll in bag)
        {
            writer.Write(coll.Count);
            foreach (Point3D point in coll)
            {
                writer.Write(point.X);
                writer.Write(point.Y);
                writer.Write(point.Z);
            }
        }
        writer.Flush();
    }

    public static void BinaryDeserialize(this ConcurrentBag<Point3DCollection> bag, Stream stream)
    {
        if (bag == null)
            throw new ArgumentNullException("bag");

        if (stream == null)
            throw new ArgumentNullException("stream");

        BinaryReader reader = new BinaryReader(stream);
        int count = reader.ReadInt32();
        for (int i = 0; i < count; i++)
        {
            int pointCount = reader.ReadInt32();
            Point3DCollection coll = new Point3DCollection(pointCount);
            for (int j = 0; j < pointCount; j++)
            {
                coll.Add(new Point3D(reader.ReadDouble(), reader.ReadDouble(), reader.ReadDouble()));
            }
            bag.Add(coll);
        }
    }
}

还有一个小的控制台应用程序测试程序可以玩:

    static void Main(string[] args)
    {
        Random rand = new Random(Environment.TickCount);
        ConcurrentBag<Point3DCollection> bag = new ConcurrentBag<Point3DCollection>();
        for (int i = 0; i < 100; i++)
        {
            Point3DCollection coll = new Point3DCollection();
            bag.Add(coll);

            for (int j = rand.Next(10); j < rand.Next(100); j++)
            {
                Point3D point = new Point3D(rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
                coll.Add(point);
            }
        }

        using (FileStream stream = new FileStream("test.bin", FileMode.Create))
        {
            bag.StringSerialize(stream); // or Binary
        }

        ConcurrentBag<Point3DCollection> newbag = new ConcurrentBag<Point3DCollection>();
        using (FileStream stream = new FileStream("test.bin", FileMode.Open))
        {
            newbag.StringDeserialize(stream); // or Binary
            foreach (Point3DCollection coll in newbag)
            {
                foreach (Point3D point in coll)
                {
                    Console.WriteLine(point);
                }
                Console.WriteLine();
            }
        }
    }
}

关于c# - 序列化 XAML 的 ConcurrentBag,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20478076/

相关文章:

c# - c#中到docker容器的连接字符串

wpf - 为什么 ListCollectionView.CustomSort 这么慢?

c# - 多线程增量并在没有锁的情况下跳过0?

c# - 获取蜂窝图案上的单元格坐标

c# - 使用smtp端口发送邮件时的异常处理

.net - EF 4.3.1和EF 5.0 DbSet.Local比实际的数据库查询要慢

c# - 为什么我要在 MSBuild 可用时继续使用 Nant?

c# - 在多线程上下文中使用超时监视文件锁释放

wpf - 将设计时资源排除在构建之外的最佳方法是什么?

c# - WPF 将按钮绑定(bind)到按下的键