My issue is regarding handling multiple backgroud worker and multiple progressbar - c#

my main problem is when i add dynamically a progressbar on flowLayoutPanel1 for each request then how can i increase right progressbar value frombackgroundWorker1_ProgressChanged event
when user click on start button then i will call RunWorkerAsync function of background worker....it is fine. here i am writing a sample code and try to show my problem.
my form has one textbox, one button and one flowLayoutPanel1 with FlowDirection topdown.
when user enter any url in textbox and click on start button then i will start file download with BackGroundWorker and add one progress bar dynamically on flowLayoutPanel1. 10 file can be downloaded at a time. so when user enter ten url one after after one and click on submit button then ten file will be downloading in background.
my problem is how to increment 10 progress bar progress properly from backgroundWorker1_ProgressChanged event another issue is when any file download will complete then the progress bar for which it has been created will be removed from panel
here is my full code. please have a look and tell me what i need to do to achieve my task. if anyone see there is problem in my code for which a dead lock may appear then also please guide me how to avoid dead lock. here is my code
public partial class Form1 : Form
{
static int pbCounter = 1;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
ProgressBar pb = new ProgressBar();
if (pbCounter <= 10)
{
pb.Width = txtUrl.Width;
flowLayoutPanel1.Controls.Add(pb);
pbCounter++;
System.ComponentModel.BackgroundWorker backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
System.ComponentModel.BackgroundWorker worker = sender as System.ComponentModel.BackgroundWorker;
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the
// RunWorkerCompleted eventhandler.
//#e.Result = ComputeFibonacci((int)e.Argument, worker, e);
}
// This event handler deals with the results of the
// background operation.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
//# "Canceled";
}
else
{
pbCounter--;
// Finally, handle the case where the operation
// succeeded.
//#resultLabel.Text = e.Result.ToString();
}
}
// This event handler updates the progress bar.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
}
MY UPDATED PART
public partial class Form1 : Form
{
static int pbCounter = 1;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
ProgressBar pb = new ProgressBar();
if (pbCounter <= 10)
{
//pb.Step = 10;
pb.Minimum = 0;
//pb.Maximum = 100;
pb.Width = txtUrl.Width;
flowLayoutPanel1.Controls.Add(pb);
pbCounter++;
MyBackgroundWorker backgroundWorker1 = new MyBackgroundWorker();
backgroundWorker1.pbProgress = pb;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerAsync(txtUrl.Text);
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int input = int.Parse(e.Argument.ToString());
for (int i = 1; i <= input; i++)
{
Thread.Sleep(2000);
(sender as MyBackgroundWorker).ReportProgress(i * 10);
if ((sender as MyBackgroundWorker).CancellationPending)
{
e.Cancel = true;
return;
}
}
}
// This event handler deals with the results of the
// background operation.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
//# "Canceled";
}
else
{
ProgressBar pb = (sender as MyBackgroundWorker).pbProgress;
if (pb != null)
{
//pb.Value = 100;
//pb.Update();
while (pb.Value <= pb.Maximum)
{
//Thread.Sleep(1000);
flowLayoutPanel1.Controls.Remove(pb);
break;
}
}
// Finally, handle the case where the operation
// succeeded.
}
}
// This event handler updates the progress bar.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressBar pb = (sender as MyBackgroundWorker).pbProgress;
pb.Refresh();
//if (e.ProgressPercentage < pb.Maximum)
// pb.Value = e.ProgressPercentage + 10;
pb.Value = e.ProgressPercentage ;
Application.DoEvents();
}
}
public class MyBackgroundWorker : System.ComponentModel.BackgroundWorker
{
public ProgressBar pbProgress = null;
public MyBackgroundWorker()
{
}
public MyBackgroundWorker(string name)
{
Name = name;
}
public string Name { get; set; }
}

This is one way of doing it -
Create your own class inherited from BackgroundWorker, Add a public variable of type ProgressBar.
Each time you add a BackgroundWorker and Progressbar dynamically, pass the progressbar object to your class.
Your derived Class -
public class MyBackgroundWorker : BackgroundWorker
{
public ProgressBar pbProgress = null;
public void BackgroundWorker()
{
}
}
Button Event Code -
private void btnStart_Click(object sender, EventArgs e)
{
ProgressBar pb = new ProgressBar();
if (pbCounter <= 10)
{
pb.Width = txtUrl.Width;
flowLayoutPanel1.Controls.Add(pb);
pbCounter++;
MyBackgroundWorker backgroundWorker1 = new MyBackgroundWorker();
backgroundWorker1.pbProgress = pb;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerAsync();
}
}
Progress Changed Event -
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
(sender as MyBackgroundWorker).pbProgress.Value = e.ProgressPercentage;
}

First declare a global dictionary and a GetInstance Method to access the form instance
public partial class Form1 : Form
{
Dictionary<String, ProgressBar> progressBars = new Dictionary<String, ProgressBar>();
static Form1 _form1 = null;
static int pbCounter = 1;
public Form1()
{
InitializeComponent();
_form1 = this;
}
public static Form1 GetInstance() {
return _form1;
}
Then with each url you get and you must be creating pb for each of them, just add them in this dictionary too
progressBars.Add("file1", pb1);
progressBars.Add("file2", pb2);
progressBars.Add("file3", pb3);
progressBars.Add("file4", pb4);
Create a function in form.cs in which you can pass the progressbar and then you can manually set the value of it.
public void ProgessReport(ProgressBar pb, int value)
{
if (pb.InvokeRequired)
{
pb.Invoke(new MethodInvoker(delegate { ProgessReport(pb, value); }));
} else
{
pb.Value = value;
}
}
now from where you are downloading the file you just have to call
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 10);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 20);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 100);
and when your second file downloads then
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 10);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 20);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 100);
like this ..

Related

How to update a listbox dynamically?

I am making a search utility and using a BackgroundWorker to search. I want that as soon as the first result is found , a new window should open up with a ListBox with the first element displayed. Now, I want that as soon as subsequent results are found, the ListBox should be updated with those results.
The method thought by me was to report the progress as soon as results are found and pass "New" and "Update" as userState to the method.
Based on the userState, I can decide whether to create a new Form or update and existing one.
Here is the code :-
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.UserState.ToString() == "New")
{
Form ResultForm = new Form();
ResultForm.Name = "ResultForm" + i.ToString();
LastFormName = ResultForm.Name;
ListBox ResultListBox = new ListBox();
ResultListBox.DataSource = SearchList;
ResultListBox.Name = "ResultListBox" + i.ToString();
LastListName = ResultListBox.Name ;
ResultForm.Container.Add(ResultListBox);
ResultListBox.Show();
ResultForm.Show();
i++;
}
else
{
;
}
}
I have stored the names of the Last open Form and it's ListBox in the variables LastFormName and 'LastListName'.
I am unable to understand what to put in the else condition, so as to update the ListBox.
What I would do is expose some properties on the popup form so that you can tell if it is open and have access to the list box.
public partial class Popup : Form
{
public bool isOpen;
public ListBox PopupListBox;
public Popup()
{
InitializeComponent();
}
void Popup_FormClosing(object sender, FormClosingEventArgs e)
{
isOpen = false;
}
private void Popup_Load(object sender, EventArgs e)
{
this.FormClosing += Popup_FormClosing;
PopupListBox = popupListBox;
}
}
Then on the calling form I would subscribe to the ProcessedChanged Event and update the listbox with the data you are passing through the ProcessedChangedEventArgs. Here is the code for the calling form
public partial class Form1 : Form
{
Popup popupForm = new Popup();
BackgroundWorker backgroundWorker = new BackgroundWorker();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker.WorkerSupportsCancellation = true;
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork += backgroundWorkerDoWork;
backgroundWorker.ProgressChanged += backgroundWorkerProgressChanged;
backgroundWorker.RunWorkerCompleted += backgroundWorkerRunWorkerCompleted;
}
void backgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
//What do you want to do if Cancelled?
}
else if (!(e.Error == null))
{
//What do you want to do if there is an error?
}
else
{
//What do you want to do when it is done?
}
}
void backgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (!popupForm.isOpen || popupForm == null)
{
popupForm = new Popup();
popupForm.Show();
popupForm.isOpen = true;
}
else
{
popupForm.Activate();
popupForm.WindowState = FormWindowState.Normal;
}
popupForm.PopupListBox.Items.Add(e.ProgressPercentage.ToString() + "%");
}
void backgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 10); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress((i * 10));
}
}
}
private void buttonStart_Click(object sender, EventArgs e)
{
if (backgroundWorker.IsBusy != true)
{
backgroundWorker.RunWorkerAsync();
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker.WorkerSupportsCancellation == true)
{
backgroundWorker.CancelAsync();
}
}
}
You shouldn't be doing work in the ProgressChanged event handler
You won't have access to the results as it is only passed an int for progress and user state
This is on the UI thread. The entire point is to do your processing on a background thread
The name DoWork event handler is clear that this is where you should do your processing.
In answer to your question. Since you create the ListBox in your event handler it goes out of scope outside the if statement. You need to create this in a more global scope. Then to add to it ResultListBox.Items.Add("ResultListBox" + i.ToString());

Running a progress bar using Background Controller in c#

I don't have a thorough knowledge about controlling threads in c#. I want to create a progress bar while running a method.
I have two forms:
Form1 is the form which show up as you run the app. It has a button called btnScrape. When it is clicked the method should be called, the form with the progress bar should show up. Form1 should be disabled to the user until the progress bar is completed.
ProgressBarForm - this has the progress bar and a label.
The code is as follows.
//In Form1.cs I have a button.
private void btnScrape_Click(object sender, EventArgs e)
{
//gather data for folloeing parameters from the form.
Controller cntrlr = new Controller(urlFilePath, destinationPath, destinationfilename,cmbDepth.SelectedIndex);
cntrlr.Vmain(); // this is the method in controller class. while this is running i want show the progress bar.
}
// in Contrller class
class Controller{
List<string> urlList = null;
URLFileReader urlFileReader = null;
HTTPWorker httpWorker = null;
SourceReader srcreader = null;
ReportWriter reportWriter = null;
string urlFilePath, destinationPath, destinationFileName;
int depth;
public Controller(string urlFilePath,string destinationPath,string destinationFileName,int depth)
{
this.urlFilePath = urlFilePath;
this.destinationPath = destinationPath;
this.destinationFileName = destinationFileName;
this.urlList = new List<string>();
this.urlFileReader = new URLFileReader();
this.httpWorker = new HTTPWorker(this.destinationPath);
this.reportWriter = new ReportWriter(this.destinationPath,this.destinationFileName);
this.srcreader = new SourceReader(this.reportWriter);
this.depth = depth;
}
//this is the method
public void Vmain(){
this.urlFileReader.ReadURL(urlFilePath);
this.urlList = urlFileReader.geturlList();
string pageSrc;
foreach (string requestUrl in urlList)
{
//do sruff for requestUrl
//the progressbar should move as the urlList iterate.
//additionally i want the label on the top of progress bar to display the current "requestUrl"
//as the urlList is over i want quit from the progressbar window and come back to Form1. Till the progrss bar is completed Form1 should be disabled for the user.
}
}
}
Please explain what is happening there and give a working code if you can. Thank you in advance. There were not any perfect answer that worked for me, even though I spent two days for this. I tried with BackgroundWorkerand threads. But no solution found. :(
In the main form you could use this code:
private Progressfrm _loadForm;
private void ShowProgress()
{
ToggleForm();
_loadForm = new Progressfrm();
_loadForm.ShowDialog();
var tcheck = new Thread(CheckLoadedProgress);
tcheck.Start();
//do stuff here
}
private void CheckLoadedProgress()
{
while (_loadForm.IsAccessible) { }
ToggleForm();
}
private void ToggleForm()
{
Invoke(new Action(() => Enabled = !Enabled));
}
private void btnScrape_Click(object sender, EventArgs e)
{
var tform = new Thread(ShowProgress);
tform.Start();
}
Then the Progress-Form will appear until it is filled:
private ProgressBar _progressBar;
private void Progressfrm_Shown(object sender, EventArgs e)
{
_progressBar = new ProgressBar { Size = new Size(100, 20), Location = new Point(10, 10) };
Controls.Add(_progressBar);
_progressBar.Show();
Refresh();
LoadProgress();
}
private void LoadProgress()
{
while (_progressBar.Value < 100)
{
_progressBar.Value++;
Thread.Sleep(100);
}
Close();
}
On this Form you have to add the Event Shown and add the code like in my example. Hope this helps.
Use BackgroundWorker class to output progressBar and statusLabel changes:
BackgroundWorker bgw;
private void btnScrape_Click(object sender, EventArgs e)
{
bgw = new BackgroundWorker();
bgw.WorkerReportsProgress = true;
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
bgw.RunWorkerAsync();
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
bgw.ReportProgress(i);
}
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
This is only an example how to update controls in an asynchron way.

How to determine that a thread is finished using c#?

I am working with threads in C#. Below is the code which I am using
// worker thread
Thread m_WorkerThread;
// events used to stop worker thread
ManualResetEvent m_EventStopThread;
ManualResetEvent m_EventThreadStopped;
private void btnSend_Click(object sender, EventArgs e)
{
if (btnSend.Text == "Cancel")
{
StopThread();
btnSend.Text = "Send";
return;
}
else
{
// initialize events
m_EventStopThread = new ManualResetEvent(false);
m_EventThreadStopped = new ManualResetEvent(false);
btnSend.Text = "Cancel";
// reset events
m_EventStopThread.Reset();
m_EventThreadStopped.Reset();
// create worker thread instance
m_WorkerThread = new Thread(new ThreadStart(this.ThreadFunction));
m_WorkerThread.Name = "Thread Sample"; // looks nice in Output window
m_WorkerThread.Start();
}
}
private void StopThread()
{
if (m_WorkerThread != null && m_WorkerThread.IsAlive) // thread is active
{
// set event "Stop"
m_EventStopThread.Set();
// wait when thread will stop or finish
try
{
Thread.Sleep(1000);
m_WorkerThread.Abort();
m_WorkerThread.Suspend();
}
catch { }
}
ThreadFinished(); // set initial state of buttons
return;
}
private void ThreadFunction()
{
// Doing My Work
}
private void ThreadFinished()
{
btnSend.Text = "Send";
}
The code above is working fine, but I have some problems.
When the threads end, btnSend.Text = "Send" is not setting.
When I press cancel, the the threads are not ending properly.
When I press cancel and close my application, the application keeps running in the background.
How can I fix these problems?
This is an example of how to use a BackgroundWorker with cancellation:
public partial class Form1 : Form
{
bool _isWorking = false;
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
backgroundWorker1.WorkerSupportsCancellation = true;
}
private void button1_Click(object sender, EventArgs e)
{
if (_isWorking)
{
// Cancel the worker
backgroundWorker1.CancelAsync();
button1.Enabled = false;
return;
}
_isWorking = true;
button1.Text = "Cancel";
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (var i = 0; i < 10; i++)
{
if (backgroundWorker1.CancellationPending) { return; }
Thread.Sleep(1000);
}
e.Result = "SomeResult";
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_isWorking = false;
button1.Enabled = true;
button1.Text = "Run";
if (e.Cancelled) return;
// Some type checking
string theResult = e.Result as string;
if (theResult == null) return; // Or throw an error or whatever u want
MessageBox.Show(theResult);
}
}

Can't seem to get progressbar to animate

OK so I've have a problem looking like this.
public Class A{
public A(){
progressBar.Style = ProgressBarStyle.Marquee;
progressBar.MarqueeAnimationSpeed = 0;
}
public void DoSomething(){
if(checkpasses){
progressBar.MarqueeAnimationSpeed = 100;
//Do something here...
progressBar.MarqueeAnimationSpeed = 0;
}
else
//Do nothing...
}
}
The problem is that my progressbar wont start moving at all. First I figured that it wont create a new thread by itself (which I find wired) so I tried creating a thread but still the same result. Nothing happens. Is it something I've forgotten?
Call
Application.EnableVisualStyles();
at the very beginning of your application.
Your "do something here" code is going to block the UI thread so you will not see the progress bar update until after the DoSomething method completes. At that time you are setting the animation speed back to 0.
Try putting your "do something here" code on a separate thread. When that thread completes set the animation speed back to 0.
Something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.MarqueeAnimationSpeed = 0;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = progressBar1.Minimum;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
DoSomething();
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.MarqueeAnimationSpeed = 100;
backgroundWorker1.RunWorkerAsync();
}
private void DoSomething()
{
Thread.Sleep(2000);
}
}
I am not sure if this is the best solution, but I have it this way:
//this is the action item (button click)
private void importSFNFReportButton_Click(object sender, EventArgs e)
{ //I run
backgroundWorker6Progress.RunWorkerAsync(); //this is how I start the progress bar 'movement'
bgwImportSF.RunWorkerAsync(); //this is another task that is lauchned after the progress bar is initiated
}
This is actual background worker
private void backgroundWorker6Progress_DoWork(object sender, DoWorkEventArgs e)
{
bool cont = true;
while (cont)
{
PauseForMilliSeconds(100);
updateProgressbar1(false);
if (noTasksExistCheck())
{
updateProgressbar1(true);
cont = false;
}
}
}
this is a delegate- I call it to auto-increase the progress bar indicator
delegate void updateProgressBarStatus(bool done);
private void updateProgressbar1(bool done)
{
if (progressBar1.InvokeRequired)
{
updateProgressBarStatus del = new updateProgressBarStatus(updateProgressbar1);
progressBar1.Invoke(del, new object[] { done });
}
else
{
if (progressBar1.Value == progressBar1.Maximum)
{
progressBar1.Value = progressBar1.Minimum;
}
progressBar1.PerformStep();
if (done == true)
{
progressBar1.Value = progressBar1.Minimum;
}
}
}
I control it via the function that has to check a global varibale
noTasksExistCheck()
This is the timer pause
public static DateTime PauseForMilliSeconds(int MilliSecondsToPauseFor)
{
System.DateTime ThisMoment = System.DateTime.Now;
System.TimeSpan duration = new System.TimeSpan(0, 0, 0, 0, MilliSecondsToPauseFor);
System.DateTime AfterWards = ThisMoment.Add(duration);
while (AfterWards >= ThisMoment)
{
System.Windows.Forms.Application.DoEvents();
ThisMoment = System.DateTime.Now;
}
return System.DateTime.Now;
}
Just to complement a bit more, the solution suggested by Dave will only work if Konstantin's suggested code exists. Otherwise, one should think of manually increasing the progressbar.value in a loop by the following code within the DoWork:
BeginInvoke(new MethodInvoker( () => progressBarSave.Value += progressBarSave.Step));

WPF ProgressBar - make the progress bar completed after the operation finished

I have a WPF form which runs a background operation with progress bar. but the problem is that;
when the operation is completed, the progress bar is still running. I mean it shows like the operation is in progress.
how can I stop that? here is my whole code;
System.ComponentModel.BackgroundWorker mWorker;
private void button1_Click(object sender, RoutedEventArgs e) {
mWorker = new System.ComponentModel.BackgroundWorker();
mWorker.DoWork +=new System.ComponentModel.DoWorkEventHandler(worker_DoWork);
mWorker.ProgressChanged +=new System.ComponentModel.ProgressChangedEventHandler(worker_ProgressChanged);
mWorker.WorkerReportsProgress = true;
mWorker.WorkerSupportsCancellation = true;
mWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
mWorker.RunWorkerAsync();
while (pbProcessing.Value != 100) {
if (!mWorker.CancellationPending) {
try {
pbProcessing.Value = (pbProcessing.Value + 0.01) % 100;
} catch (System.Exception ex) {
// No action required
}
} else {
MessageBox.Show(this, "Process cancelled", "Cancel Process", MessageBoxButton.OK);
break;
}
System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,
new System.Threading.ThreadStart(delegate { }));
}
}
private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) {
// Do your work here, its on seperate thread
System.Threading.Thread.Sleep(10000);
}
private void worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) {
pbProcessing.Value = e.ProgressPercentage;
}
private void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
// Stop Progressbar updatation
Window1 w = new Window1();
w.Browser.Navigate(new Uri("http://stackoverflow.com"));
w.Show();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
if (mWorker != null) {
if (mWorker.IsBusy) {
mWorker.CancelAsync();
}
}
}
If you want to hide the progressbar after the work is done, set its Visibility property to Visibility.Hidden. If you just want to reset it to its initial state, set it's Value to 0 (or to pbProgressing.Minimum, if you changed that from its default value).
As a side note, your code doesn't really make sense: Instead of continuously changing pbProcessing.Value in the button event handler (which is completely useless, since no UI updates are performed until the button event handler has completed), you should only change the value in ProgressChanged. I.e., your code should look something like this:
System.ComponentModel.BackgroundWorker mWorker;
private void button1_Click(object sender, RoutedEventArgs e) {
mWorker = new System.ComponentModel.BackgroundWorker();
mWorker.DoWork +=new System.ComponentModel.DoWorkEventHandler(worker_DoWork);
mWorker.ProgressChanged +=new System.ComponentModel.ProgressChangedEventHandler(worker_ProgressChanged);
mWorker.WorkerReportsProgress = true;
mWorker.WorkerSupportsCancellation = true;
mWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
mWorker.RunWorkerAsync();
// Don't do anything else here
}
private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) {
for (int i = 1; i < 100; i++) {
mWorker.ReportProgress(i);
// Do some part of the work
System.Threading.Thread.Sleep(100);
// Check if the user wants to abort
if (mWorker.CancellationPending) {
e.Cancel = true;
return;
}
}
mWorker.ReportProgress(100); // Done
}
private void worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) {
pbProcessing.Value = e.ProgressPercentage;
}
private void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
// Stop Progressbar updatation
Window1 w = new Window1();
w.Browser.Navigate(new Uri("http://stackoverflow.com"));
w.Show();
// Check the result
if (e.Cancelled) {
// show the message box that the task has been canceled
}
// Reset Progress bar
pbProcessing.Value = 0;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
if (mWorker != null) {
if (mWorker.IsBusy) {
mWorker.CancelAsync();
}
}
}

Categories