我写xml时如何增加进度条?

Gol*_*old 2 c# winforms

我有数据集ds

DataSet ds = new DataSet();
SQL = "SELECT * FROM MyCount";
adp = new SqlCeDataAdapter(SQL, Conn);
adp.Fill(ds, "MyCount");
adp.Dispose();
Run Code Online (Sandbox Code Playgroud)

我写这样的xml: ds.WriteXml(@"\MyPath\Count.xml");

我需要在执行此操作时增加进度条.

怎么做 ?

谢谢

Kei*_*thS 5

不幸的是,您可以使用WriteXml()方法使用的DataSet和TextWriter/XmlWriter都不允许您订阅任何"ValueWritten"事件,这将是最干净的方法.

如果你绝对必须有一个工作进度条,它会向用户显示你编写了多少XML,我建议你派生自己的XmlWriter实现,它将公开并触发一个可订阅的事件,你可以使用它来突破你的进度条.写.您可以在实现中包含一个XmlTextWriter来实际编写(我强烈建议这样做),但是您不能直接从XmlTextWriter派生.这是因为您将从XmlTextWriter扩展的方法不是虚拟的,因此您必须使用new关键字隐藏XmlTextWriter的实现.然后,DataSet.WriteXml(XmlWriter)重载会将您的类视为基本XmlWriter,因此您编写的隐藏XmlTextWriter实现的方法将被忽略.

您需要权衡的其他注意事项:

  • 在您通过WriteXml()告诉XmlWriter关闭它的流之前,您不会知道写入文件的确切大小.因此,每个"碰撞"都需要进行某种有根据的猜测.
  • 如果预计所有文件的大小大致相同,那么您可以提出平均"块百分比"比率,这将成为您的"步骤".
  • 您还可以尝试直接设置进度百分比,将进度条按每次读取的剩余进度的某个固定百分比移动,这会将其渐近地移至100%但在作者关闭之前不会到达(并触发一个事件说你'重做).
  • 与所有事件一样,请确保在发布者或订阅者处置时正确释放对事件的所有订阅.
  • 与所有UI元素一样,请确保您没有尝试调用与UI线程之外的进度条一起使用的处理程序.这限制了您的多线程选项,因为从另一个线程调用WriteXml将导致处理程序在该线程中运行.但是,您必须允许UI线程花费一些处理器时间来重绘条形图,因此扁平单线程选项也不起作用.考虑在幕后使用异步写入,和/或在更新进度条后执行Thread.Yield().

编辑:实际上,因为XmlWriter声明了XmlTextWriter必须实现的抽象方法,所以你可以在自定义类中进一步覆盖它们,这样你就可以直接从XmlTextWriter继承.

一些示例代码:

public class ObservableXmlTextWriter: XmlTextWriter
{
   public delegate void XmlWriteHandler(object sender, XmlWriteEventArgs e);

   public event XmlWriteHandler XmlWritten;

   public event EventHandler XmlWriteComplete;

   public class XmlWriteEventArgs:EventArgs
   {
      public object Value{get; private set;}
      public XmlWriteEventArgs(object value) {Value = value;}
   }

   public override WriteValue(string value)
   {
      base.WriteValue(value);
      if(XmlWritten != null) XmlWritten(this, new XmlWriteEventArgs(value));
   }

   public override WriteValue(int value)
   {
      base.WriteValue(value);
      if(XmlWritten != null) XmlWritten(this, new XmlWriteEventArgs(value));
   }

   ... //override ALL Write methods to fire XmlWritten as above

   //Dispose will call Close(), so just make sure to do one or the other
   public override Close()
   {
      base.Close(value);
      if(XmlWriteComplete!= null) XmlWriteComplete(this, new EventArgs()));
   }
}

...

public void XmlWriteHandler(object sender, XmlWriteEventArgs e)
{
   //Feel free to come up with your own algorithm for approaching 100%;
   //the number of times this event fires will be proportional to the
   //number of data elements (rows * columns) in the DataSet.
   MyProgressBar.Increment((MyProgressBar.Maximum - MyProgressBar.Value) * .05)
}

public void XmlWriteCompleteHandler(object sender, EventArgs e)
{
   MyProgressBar.Value = MyProgressBar.Maximum;
}
Run Code Online (Sandbox Code Playgroud)