Windows Forms Threading and Events - ListBox updates quickly, but progress bit is very delayed

Our team is creating a new workflow system to replace the old one. I was instructed to transfer the old data to a new schema. I decided to do this by creating a small Windows Forms project, because the schema is radically different, and direct TSQL scripts are not an adequate solution.

The main sealed class "ImportController", which does the work, declares the following delegate event:

public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e); public static event ImportProgressEventHandler importProgressEvent; 

The main window launches the static method in this class using the new thread:

 Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData)); dataProcessingThread.Name = "Data Importer: Data Processing Thread"; dataProcessingThread.Start(settings); 

args ImportProgressEvent contains a string message, the maximum int value for the progress bar and the current value of the current performance. The Windows form attributes to the event:

 ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent); 

And it responds to the event this way using its own delegate:

  private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax); private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e) { this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax); } 

Finally, the progress bar and list are updated:

 private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax) { string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in items) { this.lstTasks.Items.Add(item); } if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax) { this.ImportProgressBar.Maximum = progressMax; this.ImportProgressBar.Value = currentProgress; } } 

The fact is, the ListBox seems to update very quickly, but the progress indicator never moves until the batch is almost complete? what gives?

+4
source share
6 answers

@John

Thanks for the links.

@Will

There is no gain from threadpooling since I know that it will only spawn a single thread. Using a stream is a purely responsive user interface, while SQL Server is read and write. This, of course, is not a short thread.

As for the sled, you're right. But, as it turned out, my problem was between the screen and the chair in the end. It seems that I have an incapable batch of data that has many much more foreign key entries than other batches, and just happens to get the selected one at the beginning of the process, i.e. currentProgress does not receive ++ 'd for 10 seconds.

@Everything

Thank you for all your input, it made me wonder what made me look elsewhere for code, which led to the moment of my humility, when I again prove that the error is usually human :)

0
source

Perhaps you can try the BackgroundWorker component. This facilitates the threading process. Examples here:

+2
source

Perhaps outside the scope, but sometimes it is useful to make Application.DoEvents(); to make gui elements respond to user input, for example, by clicking the cancel button in the status bar dialog box.

0
source

Do you accidentally start Windows Vista? I noticed the same thing in some work-related applications. Somehow, it seems that there is a delay when the progress bar "animates."

0
source

Are you sure the user interface thread runs freely during this whole process? that is, he is not sitting locked on Join or any other waiting? This is what it seems to me.

The suggestion to use BackgroundWorker is a good one - certainly better than trying to put your sledgehammer out of the problem with the load on Refresh / Update calls.

And BackgroundWorker will use the pool thread, which is a more convenient way of behavior than creating your own short-lived thread.

-1
source

There is no gain from threadpooling as I know that it will ever spawn a single thread. Using a stream is purely having a responsive interface, while SQL Server is read and written. This, of course, is not short.

Ok, I appreciate that and I'm glad you found your mistake, but did you look at BackgroundWorker? It does pretty much what you do, but in a standardized way (i.e., without its own delegates) and without the need to create a new thread - both of which (maybe small, but maybe still useful).

-1
source

Source: https://habr.com/ru/post/1276342/


All Articles