К сожалению, ни 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;
}