The correct way to synchronize wpf runtime with a function from a library

I use a function from the library to process really large text files, and I cannot change this function. During processing, I want to show a progress bar, because in any case, the application looks frozen, and users do not know that it really works. While I use such a worker:

private void btnClick(object sender, RoutedEventArgs e) { BackgroundWorker worker = new BackgroundWorker(); worker.RunWorkerCompleted += worker_RunWorkerCompleted; worker.WorkerReportsProgress = true; worker.DoWork += worker_DoConvertOne; worker.ProgressChanged += worker_ProgressChanged; worker.RunWorkerAsync(); } private void worker_DoConvertOne(object sender, DoWorkEventArgs e) { var worker = sender as BackgroundWorker; //The progress bar is filled on 20% worker.ReportProgress(0); worker.ReportProgress(10); worker.ReportProgress(20); //Processing myLongLastingFunction(bigWordFile); //The progress bas is full worker.ReportProgress(100, "Done Processing."); } private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { MessageBox.Show("Converting finished!"); TestProgressBar.Value = 0; ProgressTextBlock.Text = ""; } private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { TestProgressBar.Value = e.ProgressPercentage; ProgressTextBlock.Text = (string)e.UserState; } 

This does the job, but this is a workaround, and I want to know if there is a right way to solve my problem. Thank you in advance.:)

+6
source share
4 answers

I take from your question that changing myLongLastingFunction not possible to give you periodic updates about progress, and this ability does not currently exist in this function.

For these scenarios, when the duration of the task cannot be determined, a progress bar with the dependency property IsIndeterminate="True" is the accepted way of providing this information to the user. This enlivens the continuous scroll of the progress bar.

Xaml

  <ProgressBar Margin="10" IsIndeterminate="True" /> 

I personally prefer animated moving points, as shown on Windows Phone. An example is implemented here .

If this is not what you need, the best method is to estimate the total time and split that time into DispatchTimer to give a periodic event to increase the progress bar. This, obviously, has two problems, either to the finish line before reaching 100% (not bad), or reaching 100%, and gets stuck there, since the actual time significantly exceeds the estimate. The second unwanted effect will make the application look inactive again.

+3
source

if you use 4.5, you can use IProgress. see this example [ https://code.msdn.microsoft.com/Progress-of-a-Task-in-C-cdb179ee†[1]

+2
source

When reading .txt (Word) files, you can show the current progress on the ProgressBar and BackgroundWorker . You just need to calculate the fraction of 1 percent for the ProgressBar . Consider an example of work:

Code behind:

 public partial class MainWindow : Window { BackgroundWorker bw; long l_file; public MainWindow() { InitializeComponent(); } string fileName = ""; private void InitializeBackgroundWorker() { bw = new BackgroundWorker(); bw.DoWork += Bw_DoWork; bw.ProgressChanged += Bw_ProgressChanged; bw.WorkerReportsProgress = true; } private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar.Value = e.ProgressPercentage; } private void Bw_DoWork(object sender, DoWorkEventArgs e) { ReadFile(fileName); } private void btnOpenFLD_Click(object sender, RoutedEventArgs e) { progressBar.Minimum = 0; progressBar.Maximum = 100; OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == true) { FileInfo fileInfo = new FileInfo(ofd.FileName); l_file = fileInfo.Length; fileName = ofd.FileName; InitializeBackgroundWorker(); bw.RunWorkerAsync(); } } private void ReadFile(string fileName) { string line; long onePercent = l_file / 100; long lineLength = 0; long flagLength = 0; using (StreamReader sr = new StreamReader(fileName, System.Text.Encoding.ASCII)) { while (sr.EndOfStream == false) { line = sr.ReadLine(); lineLength = line.Length; flagLength += lineLength+2; //Thread.Sleep(1);//uncomment it if you want to simulate a //very heavy weight file if (flagLength >= onePercent) { CountProgressBar += 1; bw.ReportProgress(CountProgressBar); flagLength %= onePercent; } } } } int countProgressBar = 0; private int CountProgressBar { get { return countProgressBar; } set { if (countProgressBar < 100) countProgressBar = value; else countProgressBar = 0; } } } 

XAML:

 <Window x:Class="BackgroundWorkerProgressBarReadFile.MainWindow" ...The code omitted for the brevity... xmlns:local="clr-namespace:BackgroundWorkerProgressBarReadFile" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="0.2*"/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> </Grid.ColumnDefinitions> <ProgressBar Margin="5" Name="progressBar"/> <Button Grid.Row="1" Content="Open File Dialog" Name="btnOpenFLD" Click="btnOpenFLD_Click"/> </Grid> </Window> 

If you do some other work after reading the file and want to show progress, just move this code after all the work you have done.

 if (flagLength >= onePercent) { CountProgressBar += 1; bw.ReportProgress(CountProgressBar); flagLength %= onePercent; } 
+2
source

If your myLongLastingFunction does not report any progress, it is impossible to determine how much of its work will be done at any time.

However, as Satyaki Chatterjee has said, you can use an endless progress indicator.

+1
source

All Articles