【问题标题】:Is there anyway to calculate or get serialization time for displaying in ProgressBar?无论如何要计算或获取在 ProgressBar 中显示的序列化时间吗?
【发布时间】:2012-08-20 05:42:30
【问题描述】:

我使用 C# .net 4.0 并且看不到任何可能的方法,但也许你知道吗? :)
我以这种方式进行序列化:

public static void SaveCollection<T>(string file_name, T list)
{
    BinaryFormatter bf = new BinaryFormatter();
    FileStream fs = null;

    try
    {
        fs = new FileStream(Application.StartupPath + "/" + file_name, FileMode.Create);
        bf.Serialize(fs, list);
        fs.Flush();
        fs.Close();
    }
    catch (Exception exc)
    {
        if (fs != null)
            fs.Close();

        string msg = "Unable to save collection {0}\nThe error is {1}";
        MessageBox.Show(Form1.ActiveForm, string.Format(msg, file_name, exc.Message));
    }
}

【问题讨论】:

  • 哇。您正在序列化如此大的东西,以至于您实际上可以在挂钟上计时?你在做 XML 序列化吗?
  • 嗯是的,我的一些可序列化的东西可能需要长达 1 分钟,这是二进制序列化 :) 只是很多对象......
  • 序列化后你的对象有多大? (平均?)
  • 9Mbs,序列化大约需要 10 秒,而集合包含 1066 个不同大小的对象。另一个例子 - 19 Mbs 和大约 30 秒的序列化,而集合有更多的对象
  • 这没有任何意义。那是。你在做 BinaryFormatter.Serialize() 以外的事情吗?

标签: c# .net serialization progress-bar binaryformatter


【解决方案1】:

我不相信有。我的建议是计算序列化需要多长时间(重复测量数百或数千次),平均它们,然后将其用作计算序列化进度的常数。

【讨论】:

  • 我希望可以做些别的事情,等一下,直到将其标记为已接受:P 谢谢
【解决方案2】:

您可以启动一个以特定频率运行的计时器(例如每秒 4 次,但这实际上与您希望更新进度的频率无关)计算当前传输数据所花费的时间,然后估计剩余时间。例如:

private void timer1_Tick(object sender, EventArgs e)
{
    int currentBytesTransferred = Thread.VolatileRead(ref this.bytesTransferred);
    TimeSpan timeTaken = DateTime.Now - this.startDateTime;

    var bps = timeTaken.TotalSeconds / currentBytesTransferred;
    TimeSpan remaining = new TimeSpan(0, 0, 0, (int)((this.totalBytesToTransfer - currentBytesTransferred) / bps));
    // TODO: update UI with remaining
}

这假设您正在另一个线程上更新 this.bytesTransferred,并且您的目标是 AnyCPU。

【讨论】:

  • 但是我可以通过哪种方式知道传输了多少字节?
  • 好吧,我不知道您如何序列化数据。但是,通常在特定的块(对象)中完成,因为每个块都被序列化,更新字段bytesTransferred(如果需要,使用Thread.VolatileWrite)。
【解决方案3】:

因此,假设您实际上事先知道对象图的大小,这本身可能很困难,但我们假设您这样做:)。你可以这样做:

public class MyStream : MemoryStream {
    public long bytesWritten = 0;
    public override void Write(byte[] buffer, int offset, int count) {                
        base.Write(buffer, offset, count);
        bytesWritten += count;
    }

    public override void WriteByte(byte value) {
        bytesWritten += 1;
        base.WriteByte(value);
    }
}

然后你可以像这样使用它:

BinaryFormatter bf = new BinaryFormatter();
var s = new MyStream();
bf.Serialize(s, new DateTime[200]);

这将为您提供写入时的字节,因此您可以使用它来计算时间。注意:您可能需要覆盖流类的更多方法。

【讨论】:

  • 如果可行,我认为这就是解决方案!我可以将 bytesWritten 作为静态成员,所以我可以读取在另一个线程(MyStream.bytesWritten)中写入了多少,该线程也更新了 ProgressBar
  • 好吧,我不会使用静态的。我将公开一个您可以订阅的 BytesWritten 事件,这样您就可以同时在同一进程中序列化多个对象,但这是另一个问题。 :)
猜你喜欢
  • 2011-01-08
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
相关资源
最近更新 更多