2 Stimmen

Wie kann ich den Fortschrittsbalken vergrößern, wenn ich Xml schreibe?

Ich habe den Datensatz ds

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

Ich schreibe an xml wie folgt: ds.WriteXml(@"\MyPath\Count.xml");

Ich muss den Fortschrittsbalken erhöhen, wenn ich diese Aktion durchführe.

wie man das macht?

danke

5voto

KeithS Punkte 67713

Leider erlauben weder das DataSet noch der TextWriter/XmlWriter, den Sie mit der WriteXml()-Methode verwenden können, ein "ValueWritten"-Ereignis zu abonnieren, was der sauberste Weg wäre, dies zu tun.

Wenn Sie ABSOLUT einen funktionierenden Fortschrittsbalken haben müssen, der dem Benutzer anzeigt, wie viel XML Sie geschrieben haben, würde ich vorschlagen, dass Sie Ihre eigene XmlWriter-Implementierung ableiten, die ein abonnierbares Ereignis bereitstellt und auslöst, das Sie verwenden können, um Ihren Fortschrittsbalken bei jedem Schreibvorgang anzustoßen. Sie können einen XmlTextWriter in Ihre Implementierung einbinden, um den Schreibvorgang tatsächlich durchzuführen (und ich empfehle Ihnen, dies zu tun), aber Sie können nicht direkt von XmlTextWriter ableiten. Das liegt daran, dass die Methoden, die Sie von XmlTextWriter erweitern werden, nicht virtuell sind, so dass Sie die Implementierung von XmlTextWriter mit der Option new Stichwort. Die Überladung DataSet.WriteXml(XmlWriter) behandelt dann Ihre Klasse als Basis-XmlWriter, so dass die von Ihnen geschriebenen Methoden, die die Implementierungen von XmlTextWriter verbergen, ignoriert werden.

Andere Überlegungen, die Sie abwägen müssen:

  • Die genaue Größe der geschriebenen Datei erfahren Sie erst, wenn Ihr XmlWriter von WriteXml() angewiesen wird, seinen Stream zu schließen(). Daher muss jeder "Bump" eine Art fundierte Schätzung sein.
  • Wenn alle Ihre Dateien ungefähr gleich groß sein sollen, können Sie ein durchschnittliches Verhältnis von "Chunk zu Prozent" ermitteln, das dann als "Schritt" dient.
  • Sie können auch versuchen, den Prozentsatz des Fortschritts direkt einzustellen, indem Sie den Fortschrittsbalken bei jedem Lesevorgang um einen festen Prozentsatz des verbleibenden Fortschritts verschieben, wodurch er sich asymptotisch auf 100 % zubewegt, diesen Wert aber erst erreicht, wenn Ihr Writer geschlossen ist (und ein Ereignis auslöst, das besagt, dass Sie fertig sind).
  • Wie bei allen Ereignissen müssen Sie sicherstellen, dass Sie alle Abonnements für das Ereignis ordnungsgemäß freigeben, wenn entweder der Herausgeber oder der Abonnent entlassen wird.
  • Wie bei allen UI-Elementen sollten Sie sicherstellen, dass Sie nicht versuchen, die Handler, die mit dem Fortschrittsbalken arbeiten, außerhalb des UI-Threads aufzurufen. Dies schränkt Ihre Multithreading-Optionen ein, da der Aufruf von WriteXml aus einem anderen Thread dazu führt, dass die Handler in diesem Thread ausgeführt werden. Allerdings müssen Sie dem UI-Thread etwas Prozessorzeit zum Neuzeichnen des Balkens zugestehen, so dass eine einfache Single-Thread-Option ebenfalls nicht funktioniert. Erwägen Sie die Verwendung asynchroner Schreibvorgänge hinter den Kulissen und/oder die Durchführung eines Thread.Yield() nach der Aktualisierung des Fortschrittsbalkens.

EDIT: Da XmlWriter abstrakte Methoden deklariert, die XmlTextWriter implementieren muss, können Sie diese in Ihrer benutzerdefinierten Klasse überschreiben, so dass Sie direkt von XmlTextWriter erben können.

Einige Beispielcodes:

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;
}

1voto

Blindy Punkte 59463

Es ist sicher, dass Sie keine Byte-für-Byte-Benachrichtigung erhalten, unabhängig davon, wie Sie die Standardsteuerung verwenden. Denken Sie daran, wie viel Overhead das bedeuten würde, vor allem, wenn jeder versucht, so hart, um Stapel schreibt zusammen.

Sie haben 2 Möglichkeiten, Ihren Fortschrittsbalken zu aktualisieren:

  • Sie setzen eine bestimmte Menge an Fortschrittsbalken "Fortschritt" für den Schreibvorgang und überspringen ihn, sobald der Schreibvorgang abgeschlossen ist; dies impliziert Vermutungen und sorgt für einen sehr "sprunghaften" Fortschrittsbalken, vor allem, wenn dieser Schreibvorgang einen großen Teil dessen ausmacht, was der Fortschrittsbalken zählt.
  • Sie geben den deterministischen Fortschrittsbalken ganz auf und verwenden stattdessen einen dieser rotierenden Fortschrittsbalken, die sich immer wieder von links nach rechts bewegen. In Windows gibt es dafür einige Beispiele.

0voto

Serkan Hekimoglu Punkte 4114

Ich denke, Sie müssen sich klarer ausdrücken. progressBar möchte, dass Sie den Min-Wert (Startpunkt) und den Max-Wert (Endpunkt) eingeben, und möchte, dass die Funktion performstep() die Schrittweite angibt. Wenn Sie 1 sagen, erhöht es 1 um 1. PerformStep() erhöht Ihren Balken. Aber wenn Sie es sofort sehen wollen, müssen Sie die Funktion

progressBar1.PerformStep();
Application.DoEvents();

normalerweise verwende ich progressBar in einer for- oder foreach-Schleife. Es gibt ein Beispiel für die Verwendung:

In Ihrer Frage, wie ich sehe, haben Sie keine Schleife. Also, wie denken Sie, um progressBar verwenden?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X