问题
I'm writing a music player. This is the (early) code that adds a directory to the playlist:
private void SelectFolderButton_Click(object sender, EventArgs e)
{
int count = 0;
AddFolderDialog.ShowDialog();
if(AddFolderDialog.SelectedPath != string.Empty)
{
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += (a,b) => playlist.AddFolder(AddFolderDialog.SelectedPath, RecursiveCheckBox.Checked, out count);
bgw.RunWorkerAsync();
bgw.RunWorkerCompleted += (a, b) => mainStatusLabel.Text = "Added " + count + " songs"; ;
bgw.RunWorkerCompleted += (a, b) => DrawPlaylist();
}
}
I just started using threads. The first question is, is this a correct code? Is there something glaringly wrong here? The second issue is that I want to regularly display the number of added songs as they're being added. Not necessarily song-by-song; once a second is fine. How do I achieve this?
回答1:
Check out this SO thread. I answered that for another user with comments. Update progress bar in MainWindow from a different Thread
Essentially, you are missing WorkerReportsProgress = true in your background worker, as well as handling the ProgressChanged event. Also, put RunWorkerAsync after you set all your events.
If you are looking at updating on regular intervals, you should use the DispatcherTimer instead, and place your methods within the Tick event.
回答2:
The Backgroundworker helps you to keep your UI responsive and is easy to use. It also cares for the multithreading stuff for you.
The Backgroundworker has a ProgressChanged event as well. The working thread can report the progress with the ReportProgress(int percentProgress)
method. If you do not know the percentage this is not problem; just pass the number of songs processed as parameter. It is your ProgressChanged event handler, which receives this number. Let it do whatever is appropriate with this number. Raise the ProgressChanged event after a certain number of songs have been processed or after a certain time has elapsed. Just remember the start-time or the time of the last progress change and look how much time has elapsed since. No need for any timer or the like.
Note also that a fundamental problem with multithreading is, that only the UI-thread (the one your main application code runs in) is allowed to interact with forms and controls. The Backgroundworker automatically calls the RunWorkerCompleted and the ProgressChanged event handlers on the UI-thread for you.
来源:https://stackoverflow.com/questions/8626164/regularly-report-progress-of-a-backgroundworker