Sorry for my Bad English
I am trying to Design a Win Form in C# which will get some Data from a database while It's loading
I want to use a progress bar to show reading data progress
I tried this code (and also many others)
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.Show();
progressBar1.Value = 10;
int n;
n = 50;//number of records in DB ,
double progress = 0;
double progstep = 25 / n;
for (int i = 1; i <= n; i++)
{
//getting
if (progress <= 100)
progressBar1.Value = (int)progress;
}
progressBar1.Value = 35;
n = 100;//number of records in DB for another data reading from DB ,
progress = 35;
progstep = 65 / n;
for (int i = 1; i <= n; i++)
{
//getting data from DB
dataGridView1.Rows.Add(....);//Adding that data to a datagrid -- parametrs removed.
progress += progress;
if (progress <= 100)
progressBar1.Value = (int)progress;
}
}
But , Problem is , Form will wait , until data reading progress be completed and I can see just a full progress bar and all data loaded.
What Should I do too fix this?
Thanks
Since this is winforms, i'd recommend using a BackgroundWorker.
Basic example:
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new DoWorkEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerAsync(//pass in object to process)
Which would then kickoff:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
//Do all of your work here
bgWorker.ReportProgress(); //percent done calculation
}
Then the Progress changed event would fire to update the UI safely:
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
This is simple mockup to show you how to work with backround worker:
First in your OnLoad
create background worker and attach 2 events to it:
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkCompleted);
bw.DoWork += new DoWorkEventHandler(DoWork);
bw.RunWorkerAsync(data); //assume data is list of numbers
private void WorkCompleted(object sender, RunWorkerCompletedEventArgs e) //after work completed remove event handlers and dispose
{
var bw = (BackgroundWorker)sender;
bw.RunWorkerCompleted -= WorkCompleted;
bw.DoWork -= DoWork;
bw.Dispose();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
var data = (List<int>)e.Argument;
foreach (var number in data)
{
if (progressBar1.InvokeRequired)
{
progressBar1.Invoke((MethodInvoker)delegate { this.ProcessNumber(number); });
}
else
{
ProcessNumber(number);
}
}
}
private void ProcessNumber(int i)
{
progressBar1.PerformStep();
//do something with i
}
Add a backgroundWorker1
to your form.
Then add a YourForm_Shown
event
private void YourForm_Shown(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Add on form's contructor after InitializeComponent()
backgroundWorker1.WorkerReportsProgress = true;
// This event will be raised on the worker thread when the worker starts
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
// This event will be raised when we call ReportProgress
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
And last add the voids of backgroundWorker1
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// The progress percentage is a property of e
progressBar1.Value = e.ProgressPercentage;
}
and
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= n; i++)
{
//getting data from DB
dataGridView1.Rows.Add(....);//Adding that data to a datagrid -- parametrs removed.
backgroundWorker1.ReportProgress(i);
// Simulate long task
}
}
Take a look at BackgroundWorker control. During form load invoke
backgroundWorker.RunWorkerAsync();
and override event DoWork to do the dirty work (load data from db) and ProgressChanged to update progress bar. In the event body (lets say the event signature will be something like this):
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
var worker = (BackgroundWorker)sender;
// time consuming operation
worker.ReportProgress(10, null);
// ... another stuff
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
progressBar.Value = e.ProgressPercentage;
}