Как увеличить прогрессбар, когда я пишу XML? - PullRequest
2 голосов
/ 05 января 2011

у меня есть набор данных ds

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

я пишу в xml так: ds.WriteXml(@"\MyPath\Count.xml");

Мне нужно увеличить прогрессбар при выполнении этого действия.

как это сделать?

спасибо

Ответы [ 3 ]

5 голосов
/ 05 января 2011

К сожалению, ни DataSet, ни TextWriter / XmlWriter, которые вы можете использовать с методом WriteXml (), не позволяют подписаться на любое событие «ValueWritten», которое было бы самым чистым способом сделать это.

Если вы АБСОЛЮТНО ДОЛЖНЫ ИМЕТЬ рабочую полосу прогресса, которая будет показывать пользователю, сколько XML вы написали, я бы посоветовал вам получить собственную реализацию XmlWriter, которая будет выставлять и запускать подписываемое событие, которое вы можете использовать, чтобы поднять ваш прогресс бар с каждой записью. Вы можете использовать XmlTextWriter в своей реализации, чтобы фактически выполнять запись (и я настоятельно рекомендую это делать), , но вы не можете напрямую наследовать XmlTextWriter. Это связано с тем, что методы, которые вы будете расширять из XmlTextWriter, не являются виртуальными, поэтому вам придется скрыть реализацию XmlTextWriter с ключевым словом new. Перегрузка DataSet.WriteXml (XmlWriter) будет затем рассматривать ваш класс как базовый XmlWriter, поэтому написанные вами методы, которые скрывают реализации XmlTextWriter, будут игнорироваться.

Другие соображения, которые вам нужно взвесить:

  • Вы не будете знать точный размер записанного файла, пока ваш XmlWriter не скажет Close () свой поток с помощью WriteXml (). Таким образом, каждый «удар» должен быть своего рода обоснованным предположением.
  • Если ожидается, что все ваши файлы будут примерно одинакового размера, вы можете придумать среднее отношение «кусок к проценту», которое станет вашим «шагом».
  • Вы также можете попытаться установить процент выполнения напрямую, перемещая индикатор выполнения на некоторый фиксированный процент оставшегося прогресса при каждом чтении, что будет асимптотически перемещать его к 100%, но не достигнет его, пока ваш писатель не закроется (и не сработает событие говорит, что вы сделали).
  • Как и во всех событиях, убедитесь, что вы правильно отменили все подписки на событие, когда выбрасывается либо издатель, либо подписчик.
  • Как и для всех элементов пользовательского интерфейса, убедитесь, что вы не пытаетесь вызывать обработчики, которые работают с индикатором выполнения вне потока пользовательского интерфейса. Это ограничивает ваши возможности многопоточности, так как вызов WriteXml из другого потока приведет к запуску обработчиков в этом потоке. Но вы должны позволить потоку пользовательского интерфейса некоторое процессорное время перерисовать панель, чтобы плоский однопоточный параметр тоже не работал. Попробуйте использовать асинхронную запись за кулисами и / или выполнить Thread.Yield () после обновления индикатора выполнения.

EDIT: На самом деле, поскольку 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;
}
1 голос
/ 05 января 2011

Это безопасная ставка, вы не получите побайтовое уведомление, независимо от того, как вы поступите со стандартными элементами управления.Подумайте о том, сколько это может означать накладных расходов, особенно когда все так стараются выполнить пакетную запись вместе.

У вас есть два способа действительно обновить индикатор выполнения:

  • вы установилиуказанное количество индикатора выполнения для выполнения записи и пропустить его после завершения записи;это подразумевает угадывание и обеспечивает очень «скользкую» шкалу прогресса, особенно если эта запись является основной частью того, что подсчитывает индикатор выполнения.
  • вы полностью отказываетесь от детерминированной индикации выполнения и вместо этого используете одну из этихвращающиеся индикаторы выполнения, идущие слева направо снова и снова.Вы можете увидеть немало примеров в Windows.
0 голосов
/ 05 января 2011

Вы должны быть более ясным, я думаю. progressBar хочет, чтобы вы вводили минимальное значение (начальная точка) и максимальное значение (конечная точка), и хочет, сколько шага будет пройдено в функции executetep (). Если вы говорите 1, это увеличивает 1 на 1. PerformStep () увеличивает вашу планку. Но если вы хотите увидеть это мгновенно, вы должны использовать

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

обычно я использую progressBar в цикле for или foreach. Есть пример использования:

В вашем вопросе, как я вижу, у вас нет петли. Так как вы думаете использовать прогрессбар?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...