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());
Related
In form1 top:
ExtractImages ei = new ExtractImages();
In form1 constructor i start the backgroundworker first time
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
}
In dowork event
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return; // this will fall to the finally and close everything
}
else
{
ei.ProgressChanged += (senders, eee) => backgroundWorker1.ReportProgress(eee.Percentage, eee.StateText);
ei.Init();
}
}
In progresschanged
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressBar1.Value = e.ProgressPercentage;
label7.Text = e.UserState.ToString();
label8.Text = e.ProgressPercentage + "%";
}
In completed
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null) { ProgressBar1.Value = 100; }
else
{
}
}
In the class top
public bool WebProblem = false;
public class ProgressEventArgs : EventArgs
{
public int Percentage { get; set; }
public string StateText { get; set; }
}
public event EventHandler<ProgressEventArgs> ProgressChanged;
public void Init()
{
object obj = null;
int index = 0;
ExtractCountires();
foreach (string cc in countriescodes)
{
// raise event here
ProgressChanged?.Invoke(obj, new ProgressEventArgs { Percentage = 100 * index / countriescodes.Count, StateText = cc });
ExtractDateAndTime("http://www.sat24.com/image2.ashx?region=" + cc);
index += 1;
}
ImagesLinks();
}
Method in class
public void ExtractDateAndTime(string baseAddress)
{
try
{
var wc = new WebClient();
wc.BaseAddress = baseAddress;
HtmlDocument doc = new HtmlDocument();
var temp = wc.DownloadData("/en");
doc.Load(new MemoryStream(temp));
var secTokenScript = doc.DocumentNode.Descendants()
.Where(e =>
String.Compare(e.Name, "script", true) == 0 &&
String.Compare(e.ParentNode.Name, "div", true) == 0 &&
e.InnerText.Length > 0 &&
e.InnerText.Trim().StartsWith("var region")
).FirstOrDefault().InnerText;
var securityToken = secTokenScript;
securityToken = securityToken.Substring(0, securityToken.IndexOf("arrayImageTimes.push"));
securityToken = secTokenScript.Substring(securityToken.Length).Replace("arrayImageTimes.push('", "").Replace("')", "");
var dates = securityToken.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var scriptDates = dates.Select(x => new ScriptDate { DateString = x });
foreach (var date in scriptDates)
{
DatesAndTimes.Add(date.DateString);
}
}
catch(WebException wex)
{
WebProblem = true;
}
}
What i want to do is once the WebProblem is true stop the loop in the Init() and stop/cancel the backgroundworker in form1.
Then in the backgroundworker completed event throw a message to a label about the problem. And start a timer and after 30 seconds start the backgroundworker again.
If the exception happen and i will use a break point in the catch and click continue it will continue but i want that once there was a problem stop everything and start over again until it will pass without any problem in the middle.
A lot of really peculiar stuff there. I suggest starting with a BackgroundWorker tutorial. Suggestions about what you have posted:
The form constructor is a really bad place to call .RunWorkerAsync; especially if you want to be able to restart the background process again. If you really want to start your BackgroundWorker immediately, you should call something like this in your Form_Load method:
backgroundWorker1.RunWorkerAsync(new Uri("http://www.sat24.com/image2.ashx"));
Your DoWorkEventHandler is where you should do your background work, check for cancellation, and report results and you aren't doing any of those. You want something like:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var result = new List<DateString>();
var baseUri = (Uri)e.Argument;
var countryCodes = ExtractCountries();
foreach (var cc in countryCodes)
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
result.Add(ExtractDateAndTime(new Uri(baseUri, "?region=" + cc));
}
e.Result = result;
}
You want ExtractCountries to return an IEnumerable of whatever data you want to enumaerate, and ExtractDateAndTime to accept a complete Uri and return a list of the results. Do not embed that logic in the methods or use globals to return the results; everything you need is already a part of BackgroundWorker, do not create a new class just to hand off the data. Your ExtractDateAndTime declaration should look like this:
private DateString ExtractDateAndTime(Uri source)
Do not catch exceptions in ExtractDateAndTime; doing that will discard the exception and continue as if nothing was wrong, then return the wrong answer without warning. If you want to display the exception, let it propagate to the RunWorkerCompleted event and inspect RunWorkerCompletedEventArgs.Error.
If you want to restart the BackgroundWorker if you get an error you want to declare a Form.Timer in your Design view or Form constructor and a Tick EventHandler something like:
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
backgroundWorker1.RunWorkerAsync(new Uri("http://www.sat24.com/image2.ashx"));
}
In your RunWorkerCompletedEventHandler do something like:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
AlertUserSomehow(e.Error);
timer1.Interval = 30000;
timer1.Start();
return;
}
DoSomethingWith((List<DateString>)e.Result);
}
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.
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 ..
I am new in C#. I found some code which work on progressbar. What is does, when someone click on button start btnStartAsyncOperation_Click the progress bar starts increasing and when btnCancel_Click is pressed it cancel the operation. Here is the code
namespace BackgroundWorkerSample
{
public partial class Form1 : Form
{
BackgroundWorker m_oWorker;
public Form1()
{
InitializeComponent();
m_oWorker = new BackgroundWorker();
m_oWorker.DoWork += new DoWorkEventHandler(m_oWorker_DoWork);
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(abcd);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
}
void abcd(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
}
btnStartAsyncOperation.Enabled = true;
btnCancel.Enabled = false;
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
}
void m_oWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
m_oWorker.ReportProgress(i);
if (m_oWorker.CancellationPending)
{
e.Cancel = true;
m_oWorker.ReportProgress(0);
return;
}
}
//Report 100% completion on operation completed
m_oWorker.ReportProgress(100);
}
private void btnStartAsyncOperation_Click(object sender, EventArgs e)
{
btnStartAsyncOperation.Enabled = false;
btnCancel.Enabled = true;
//Start the async operation here
m_oWorker.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (m_oWorker.IsBusy)
{
//Stop/Cancel the async operation here
m_oWorker.CancelAsync();
}
}
private void progressBar1_Click(object sender, EventArgs e)
{
}
private void lblStatus_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
Now I added 2 more button, button1 to pause and button2 to resume. Since I could not find any method to resume, I had to use CancelAsync() function when I press pause and I keep the value of progress bar in a global variable. Then when I press resume I start the progress bar again using RunWorkerAsync. But the problem is, I can not send the value of global variable in this function so it start from 0 progress.
I tried to use thread.sleep(infinite time here) when someone press pause and then stop the thread when someone press resume. Still the problem is, I can not press any button in this situation. Still if I enable button they don't work.
Please give me some solution.
You could try having your own variable, i.e
bool isPaused = false;
When someone clicks your pause button...
isPaused = true;
And set it to false when someone clicks resume. Finally, in your for loop in your doWork method, make it wait until that variable is false.
while (isPaused)
{
Thread.Sleep(100);
}
Let me know how this works out for you.
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();
}
}
}