Background worker not starting - c#

I've implemented a background worker onLoad of my window. The code in the Progress_Load is reached but after that the DoWork function is not called. The function excel.Read() reads a quite big excel tabel into a list, this takes about 1.5 min and that's why i want to do it a-syn.
public List<Part> partList = new List<Part>() { };
//boolean that will be set when the backgroundworker is done
public bool listRead = false;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
_Excel excel = new _Excel();
partList = excel.Read();
backgroundWorker1.ReportProgress(100);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Message m;
if (e.Cancelled == true)
{
m = new Message("The operation has been canceld!", "Canceled");
this.Close();
}
else if (e.Error != null)
{
Error er = new Error("Error: " + e.Error.Message, "Error!");
this.Close();
}
else
{
listRead = true;
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Change the value of the ProgressBar to the BackgroundWorker progress.
progressBar1.Value = e.ProgressPercentage;
//Set the text.
this.Text = e.ProgressPercentage.ToString();
}
private void Progress_Load(object sender, EventArgs e)
{
if (backgroundWorker1 == null)
{
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.RunWorkerAsync();
}

Probably it's not null when loading the form. You may have added the BackgroundWorker via the designer. If so it's never null, you can hook up the event handlers also from its Properties/Events.
Try this
private void Progress_Load(object sender, EventArgs e)
{
if (backgroundWorker1 == null)
{
backgroundWorker1 = new BackgroundWorker();
}
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.RunWorkerAsync();
}
In WPF Dispatcher.BeginInvoke(DispatcherPriority.Background, workAction); is a another option because report progress is not much useful in your scenario. Here example for Dispatcher and Background worker comparison.

Related

WPF closing a dialog automatically after background worker is completed

When I click the login button, my background worker starts processing and a loading dialog window shows up.
However, how can I close it after my task has been completed?
private void LoginButton_Click(object sender, RoutedEventArgs e)
{
AdjustControls(false);
if (Username == null)
{
Error("Username required");
return;
}
loading.ShowDialog();
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += login_backgroundWorker_DoWork;
backgroundWorker.ProgressChanged += login_backgroundWorker_ProgressChanged;
backgroundWorker.RunWorkerCompleted += login_backgroundWorker_RunWorkerCompleted;
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.RunWorkerAsync();
}
private void login_backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
var backgroundWorker = sender as BackgroundWorker;
try
{
this.Dispatcher.Invoke(new MethodInvoker(delegate ()
{
loading.ShowDialog();
Action closeAction = () => loading.Close();
loading.Dispatcher.Invoke(closeAction);
this.Close();
}));
}
catch (Exception InputChangedException)
{
Console.WriteLine(InputChangedException);
if (InputChangedException != null)
{
Error(InputChangedException.Message);
}
}
}
private void login_backgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
}
private void login_backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
this.Dispatcher.Invoke(new MethodInvoker(delegate ()
{
loading.Close();
}));
}
I found the answer and it seems quite simple. I just needed to set an Action:
this.Dispatcher.BeginInvoke(new Action(() => loading.ShowDialog()));
This is to start it, then another time to close it

BackgroundWorker doesn't trigger DoWork_Event

BackgroundWorker worker = new BackgroundWorker();
private void btn_Start_Click(object sender, EventArgs e)
{
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.WorkerReportsProgress = true;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
using (WebClient webclient = new WebClient())
{
using (SPSite site = new SPSite(tb_sourceSite.Text))
{
using (SPWeb web = site.OpenWeb())
{
webclient.Credentials = new NetworkCredential(tb_NC_Username.Text, tb_NC_Password.Text, tb_NC_Domain.Text);
SPList list = web.Lists[tb_sourceList.Text];
SPQuery qry = new SPQuery();
qry.Query = "<OrderBy><FieldRef Name='ID' /></OrderBy>";
qry.RowLimit = Convert.ToUInt32(NumberOfImages.Value);
SPListItemCollection items = list.GetItems(qry);
int i = 0;
progressBar1.Maximum = items.Count;
foreach (SPListItem item in items)
{
string filePathUrl = String.Concat(web.Url, "/", item.Url);
webclient.DownloadFile(filePathUrl, tb_DownloadFolder.Text);
worker.ReportProgress(i);
i++;
}
}
}
}
}
The Startbutton works, i can debug into it.
But nothing happens in Backgroundworker.
It doesn't download anything oder changes anything.
I am new to Backgroundworker. Am I doing something wrong?
while debugging you might get cross-thread error. Try by creating a delegate to set label text. The below code is just a short example how to use BackgroundWorker with delegate.
delegate void SetLabel(string msg);
BackgroundWorker worker = new BackgroundWorker();
private void btn_Start_Click(object sender, EventArgs e)
{
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.WorkerReportsProgress = true;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.Invoke(new SetLabel(SetLabelMethod), new object[]{
"Connecting..."})
}
void SetLabelMethod(string msg)
{
lbl_status.Text = msg;
}

How to use ProgressBar Control with DataGridView

I want to use a ProgressBar control in C# when my DataGridView is loading data, but when I run my program I get an error:
Cross-thread operation not valid: Control 'dataGridView1' accessed from a thread other than the thread it was created on.
Code:
private readonly BackgroundWorker _bw = new BackgroundWorker();
public workerbloks()
{
InitializeComponent();
progressBar1.MarqueeAnimationSpeed = 30;
// set Visible false before you start long running task
progressBar1.Visible = false;
_bw.DoWork += show_worked_bloks;
_bw.RunWorkerCompleted += BW_RunWorkerCompleted;
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Show();
_bw.RunWorkerAsync();
}
private void BW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Hide();
}
public void show_worked_bloks(object sender, DoWorkEventArgs doWorkEventArgs)
{
MYDBMS md = new MYDBMS();
DataTable dt = new DataTable();
clsWorkBloks clswb = new clsWorkBloks();
try
{
dt = md.ExecuteSelectSQL(clswb.show_all_worked_bloks());
dataGridView1.DataSource = dt;
}
catch
{
}
}
Execute the specified delegate asynchronously on the thread that the dataGridView1 underlying handle was created on.
dataGridView1.BeginInvoke((MethodInvoker)delegate
{
this.dataGridView1.DataSource = dt;
});
As the progressbar is just marquee display. Simply bring it to front before running background worker.
progressBar1.BringToFront();
progressBar1.Show();
_bw.RunWorkerAsync();

BackgroundWorker WPF difficulties with Progress Bar

I am developing a WPF, C# application and I have to read a very big CSV file and write to a database. This process takes a long time so I want to at least show a progress bar that grows in size as it nears completition.
Now, I have the following code at the top:
private readonly BackgroundWorker worker = new BackgroundWorker();
Then inside the loop I have this:
worker.WorkerReportsProgress = true;
worker.ReportProgress((100 * i) / 10000);
and I have a private sub like this:
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
prgBar.Value = Math.Min(e.ProgressPercentage, 100);
}
Yet I don't see the progress bar updating or anything happening, program still hangs. Am I doing something wrong?
UPDATE: Tried the MSDN guide here http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx and I somehow failed to get it working with that example. I adjusted the looping part of course. Heh. It still stays idle and nothing updates. Heck, all I want to do is get a small counter that increases every time a line is read and added.
UPDATED CODE:
private BackgroundWorker bw = new BackgroundWorker();
public Process()
{
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Perform a time consuming operation and report progress.
int d = 0;
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Set filter for file extension and default file extension
dlg.DefaultExt = ".csv";
dlg.Filter = "CSV File (*.csv)|*.csv";
dlg.Title = "file";
// Display OpenFileDialog by calling ShowDialog method
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
// Open document
string filename = dlg.FileName;
List<String[]> fileContent = new List<string[]>();
using (FileStream reader = File.OpenRead(#filename)) // mind the encoding - UTF8
using (TextFieldParser parser = new TextFieldParser(reader))
{
using (SqlConnection conn = new SqlConnection(Classes.PublicVariables.Connection))
{
parser.Delimiters = new[] { "," };
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
string[] line = parser.ReadFields();
fileContent.Add(line);
SqlCommand comm = QUERYANDPARAMETERS
d += 1;
comm.ExecuteNonQuery();
worker.ReportProgress((d * 10));
}
}
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lblCount.Content = "Complete";
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.lblCount.Content = (e.ProgressPercentage.ToString() + "%");
}
I am getting an excerption when the worker runs.
An exception of type 'System.NullReferenceException' occurred inSolution.exe but was not handled in user code
Additional information: Object reference not set to an instance of an object.
UPDATE3
Got it working! All I needed was the same code as above but this:
if (bw.IsBusy != true)
{
bw.RunWorkerAsync();
}
else
{
bw_DoWork(null, null);
}
In the event handler for the button press.
This will not compile as-is, but should get you started in the right direction:
private readonly BackgroundWorker worker
= new BackgroundWorker { WorkerReportsProgress = true };
public MainWindow()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
}
private void worker_DoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
// Do some long process, break it up into a loop so you can periodically
// call worker.ReportProgress()
worker.ReportProgress(i); // Pass back some meaningful value
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
prgBar.Value = Math.Min(e.ProgressPercentage, 100);
}
is the varible i int? if it is, the value of (100 * i) / 10000 will return 0 while i < 100. and the param of ReportProgress method should be a precent value. you can change it to worker.ReportProgress(i);,try it.

UI hangs when long search loop executed in c#

in my Winform a read file method is implemented on button click.when big files are read my Ui hangs until the loop is over.I need to have control on my UI all the time.
i know that is done before and i tried some but i am still having an
error when i try to use some form controls like this :(translated!)
the access of control element comboBox1 is from another thread rather than the thread in which it is created in !!!
private void button1_Click(object sender, EventArgs e)
{
//some code
using (StreamReader sr = new StreamReader(file, System.Text.Encoding.ASCII))
{
while (sr.EndOfStream == false)
{
line = sr.ReadLine();
UpdateProgressBar(line.Length);
}
}
//some code
}
Add a BackgroundWorker to your class on Form (or Control) load. Then hookup its events:
BackgroundWorker _worker;
void Form_Load(object sender, EventArgs e)
{
_worker = new BackgroundWorker();
_worker.DoWork += _worker_DoWork;
_worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
_worker.ProgressChanged +=_worker_ProgressChanged;
_worker.WorkerReportsProgress = true;
}
private void button1_Click(object sender, EventArgs e)
{
_worker.RunWorkerAsync(file);//pass on the file name
}
private void _worker_DoWork(object sender, DoWorkEventArgs e)
{
var file = e.Argument as String;
using (StreamReader sr = new StreamReader(file, Encoding.ASCII))
{
while (sr.EndOfStream == false)
{
line = sr.ReadLine();
_worker.ReportProgress(line.Length);
}
}
}
private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Report porogress bar change
UpdateProgressBar(e.ProgressPercentage);
}
private void _worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
//do any stuff you want after reading the file.
}
Read more about this here.
Use a BackgroundWorker to do the work on a separate thread.
Use BackgroundWorker
[edit] Tutorial available here
You really should have consulted the documentation before asking a question. Anyways, here's an example of how you can do it using a BackgroundWorker:
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker;
worker.WorkerReportsProgress = true;
worker.ProgressChanged += ProgressChanged;
worker.DoWork += ReadStream;
worker.RunWorkerAsync(comboBox1.Text);
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
UpdateProgressBar(e.ProgressPercentage);
comboBox1.Text = e.UserState.ToString();
}
private void ReadStream(object sender, DoWorkEventArgs doWorkEventArgs)
{
BackgroundWorker worker = sender as BackgroundWorker;
string line;
string comboBoxText = doWorkEventArgs.Argument.ToString();
using (StreamReader sr = new StreamReader("file", System.Text.Encoding.ASCII))
{
while (!sr.EndOfStream)
{
line = sr.ReadLine();
worker.ReportProgress(line.Length);
worker.ReportProgress(line.Length, "NEW COMBOBOX TEXT");
}
}
}
use backgroundworker to carry out heavy operations.
it has event to report progress of the task , so you can use it to update progress bar.

Categories