I'm currently learning C#, implementing a project with Visual Studio Community. I want it clean and appropriately organized from the start, so, as a general rule, I try not to mix the UI code with the underlying logic; also, I'd like specific parts the code to be used across the whole project.
Hence I made a class populationIdParserWorker
in a separate file than the respective UI element, PopulationIdParser
. It worked just fine, until I came up with an idea to add a progress bar to the UI. I learned that to make it actually show the progress, I can use BackgroundWorker
to introduce the necessary multi-threading. I've been doing some research on how to use it, but I only found such examples, where the actual logic was done inside the UI code, which doesn't seem appropriate to me in terms of bigger projects. So I came up with the idea to pass my worker_DoWork
method's arguments to the actual logic, located in populationIdParserWorker
class' method process_file_lite
. Is it a good practice or should it be done another way? How else can I do it?
Side note: The thing isn't working quite the way it is supposed to, because the progress bar is reaching some point and then the UI holds for a moment, only for the bar to jump to the end immediately. I'm not sure if it has something to do with my method of passing the arguments as a reference - I'm going to check it soon. I'm not convinced yet, because the bar freezes just after all true work has been done, i.e. the remaining lines of the file are meaningless, so they are being read and skipped.
Here are the pieces of code:
From PopulationIdParser.xaml.cs
:
private void GenerateFiles_Click(object sender, RoutedEventArgs e)
{
ParsingStatus.Value = 0;
parsingStatusBarPassing.set_all(Convert.ToInt32(ParsingStatus.Minimum), Convert.ToInt32(ParsingStatus.Maximum),
new IntWithPercentScale(ParsingStatus.Value, ParsingStatus.Maximum));
parserPathsArgs.set_all(parsingStatusBarPassing,
SaveBrowser.Text, UsedBrowser.Text, FreeBrowser.Text, default_profs_name);
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync(parserPathsArgs);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
populationIdParserWorker.process_file_lite(ref sender, ref e);
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ParsingStatus.Value = e.ProgressPercentage;
if(e.UserState != null)
{
ParsingPercentage.Text = (e.UserState).ToString() + "%";
}
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done.");
}
From PopulationIdParserWorker.cs
:
public void process_file_lite(ref object sender, ref DoWorkEventArgs e)
{
///A file is opened here, some pre-processing is done
while ((line = file.ReadLine()) != null)
{
///Parsing is done here
parsingProgress = Convert.ToInt32(((double)i / flen) * parsingStatusBar.maximum);
parsingProgressPercentage = Convert.ToInt32(parsingProgress / parsingStatusBar.value.get_scale());
(sender as BackgroundWorker).ReportProgress(parsingProgress, parsingProgressPercentage);
i++;
}
}
In PopulationIdParser.xaml.cs
: ParsingStatus
is the progress bar; parsingStatusBarPassing
and parserPathsArgs
are utility objects used to store the data to be passed between different classes, UIs, threads etc.
In PopulationIdParserWorker.cs
: 'flen' is the lines count of the processed file and parsingStatusBar
is an object to store information about the progress bar showing the parsing status.