cancel process by clicking a button - c#

There is a process in the project I wrote. It takes time, and I want to use a progress bar. I want to allow the user to cancel the process and the ProgressBar by clicking a button. I do not want the user to be able to click any other controls on that form when my process is running. If I use a thread, then the user can click other controls on the form.
Perhaps one solution is to use another form, and set the ProgressBar and cancel button on the second form. But how can I set the value of the ProgressBar according my process, which is taking part on the first form.
What's the solution?
Thanks in advance.

This is best done with a dialog, it automatically makes the rest of your UI inaccessible. Add a new form to your project and drop a ProgressBar and a Button on it. And add a public method so you can update the progress bar from the event handler in your main form:
public partial class ProgressDialog : Form {
public ProgressDialog() {
InitializeComponent();
}
public void ShowProgress(int progress) {
progressBar1.Value = progress;
}
private void CancelProcess_Click(object sender, EventArgs e) {
this.DialogResult = DialogResult.Cancel;
}
}
You'll need to display the dialog when you start the worker:
ProgressDialog dlg;
private void RunProcess_Click(object sender, EventArgs e) {
backgroundWorker1.RunWorkerAsync();
using (dlg = new ProgressDialog()) {
dlg.ShowDialog(this);
}
dlg = null;
if (backgroundWorker1.IsBusy) backgroundWorker1.CancelAsync();
}
Note how it calls CancelAsync() to stop the worker so closing the dialog is enough to make it stop. You'll need to update the progress bar:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
dlg.ShowProgress(e.ProgressPercentage);
}
And you need to automatically close the dialog when the worker completes and the user hasn't close the dialog herself:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (dlg != null) dlg.Close();
}

Use a BackgroundWorker, this provides an API for reporting progress and cancellation.

Use BackgroundWorker for that. Add it to your first form and on BackgroundWorker progress changed event change progress bars value. Look at example shown in documentation.

Related

c# - Pass string between voids and update in timer [duplicate]

Right now, I'm using a background worker thread to check something every so often and if the conditions are met a messagebox is generated.
I didn't notice for awhile that because I'm calling the messagebox in the background worker I lose the usual messagebox behavior of not letting the user click back on the main form before they click yes/no/cancel on the messagebox.
So, is there some option on the messagebox to keep it in the foreground always? Or is it possible to send a message from the background worker to the main form so I can generate the messagebox from there? Is there another way?
Thanks
Isaac
A background worker is a different thread than your windows form. Therefor you need to let your background worker somehow return information back to the main thread.
In the example below, I use the reportProgress functionality of the backgroundworker, as the event is triggered on the windows form thread.
public partial class Form1 : Form
{
enum states
{
Message1,
Message2
}
BackgroundWorker worker;
public Form1()
{
InitializeComponent();
worker = new BackgroundWorker();
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.WorkerReportsProgress = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
//Fake some work, report progress
worker.ReportProgress(0, states.Message1);
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
states state = (states)e.UserState;
if (state == states.Message1) MessageBox.Show("This should hold the form");
}
private void button1_Click(object sender, EventArgs e)
{
worker.RunWorkerAsync();
}
}
Note: The background worker will NOT halt at reportProgress. If you want your bgworker to wait until the mbox is pressed, you need to make a halt something manually for it.
You can use the Invoke method of the Form1 class to invoke that form's UI thread.
this.Invoke(() => MessageBox.Show("Hi"));

Need loading GIF or progress bar while navigating from one page to another

First page
private void Button_Click(object sender, RoutedEventArgs e)
{
Page1 p1 = new Page1();
this.NavigationService.Navigate(p1);
}
Second Page(Page 1 as specified in the code )
public Page1()
{
InitializeComponent();
Thread.Sleep(10000);
}
get loading icon or progress bar while navigating from page 3 to page 1 on button click.
As soon as the user clicks on the button on page 3 this page hangs until page 1 processes the data in the background
Code will be preferable
i have found this example at codeproject you give a look to the example. I hope this is help
How to set progress bar during one page to another page load in c# .net windows application?
This gets asked almost daily so I've written this short demonstration code to demonstrate how to use a System.ComponentModel.BackgroundWorker in combination with a System.Windows.Forms.ProgressBar. All the code is commented so the flow/steps should be easy to understand.
Just drop a ProgressBar (progressBar1) and a BackgroundWorker (backgroundWorker1) onto your form and copy and paste this code to see it in action.
Hide Shrink Copy Code
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Shown += new EventHandler(Form1_Shown);
// To report progress from the background worker we need to set this
property
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);
}
void Form1_Shown(object sender, EventArgs e)
{
// Start the background worker
backgroundWorker1.RunWorkerAsync();
}
// On worker thread so do our thing!
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Your background task goes here
for (int i = 0; i <= 100; i++)
{
// Report progress to 'UI' thread
backgroundWorker1.ReportProgress(i);
// Simulate long task
System.Threading.Thread.Sleep(100);
}
}
// Back on the 'UI' thread so we can update the progress bar
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// The progress percentage is a property of e
progressBar1.Value = e.ProgressPercentage;
}
}

Request using BackgroundWorker never seems to complete

I created a Loading Window for my Login form, and I use BackgroundWorker to make a smooth Loading animation, but if I use ShowDialog() insted of Show(), the Loading Window stays on screen, and the program does nothing. What's causing this?
Here I invoke the BackgroundWorker and I show the Loading page:
private void loginButton_Click(object sender, EventArgs e) {
loadscr.Show();
LoginBV.RunWorkerAsync();
}
and here I close the Loading Window:
private void LoginBV_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
loadscr.Close();
//and show the MainWindow, etc.
}
The DoWork(BackgroundWorker) code:
private void LoginBV_DoWork(object sender, DoWorkEventArgs e) {
NameValueCollection POST = new NameValueCollection();
POST["username"] = ipbUN.Text;
POST["password"] = ipbPASS.Text;
POST["pin"] = ipbPIN.Text;
POST["csoport"] = "user";
var action = Program.startPOST<DataObj>("http://localhost/system/winapi.php?do=userlogin", POST);
finish["sessionkey"] = action.sessionkey;
finish["status"] = Convert.ToString(action.status);
}
See MSDN article on ShowDialog.
"You can use this method to display a modal dialog box in your
application. When this method is called, the code following it is not
executed until after the dialog box is closed."
Using modal dialogs (ShowDialog) stops the execution of the code following it until something/someone dismisses the dialog. It "pauses" your program. The background worker is never run because you start it after calling ShowDialog.

Close busy form when background-worker is complete?

I have an application that when busy will open a busy form (FormWaitingForm) to indicate to the user that the application is busy. How do i close FormWaitingForm in the event backgroundWorker1_RunWorkerCompletedbelow ?
private void radButtonCheckFiles_Click(object sender, EventArgs e)
{
var bw = new BackgroundWorker();
// define the event handlers
bw.DoWork += new DoWorkEventHandler(ProcessTickTemp);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
bw.RunWorkerAsync(); // starts the background worker
// execution continues here in parallel to the background worker
using (var FormWaitingForm = new WaitingForm()) //
{
var result = FormWaitingForm.ShowDialog();
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// How do i close FormWaitingForm here ?
}
You could try something like this. Retain a reference to the form outside of the click method and then open it non-modally (so that you don't have to wait for the user to close it).
WaitingForm formWaitingForm;
private void radButtonCheckFiles_Click(object sender, EventArgs e)
{
// background code here
formWaitingForm = new WaitingForm();
formWaitingForm.Show();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
formWaitingForm.Close();
formWaitingForm.Dispose();
}
You would have to add some code to handle if the user closes the waiting form without waiting for you to do it.
That said, the way I usually implement a waiting/progress-type form is to incorporate the background process into the progress form itself and show something like a progress bar.
This link might give you some more ideas.

Can not click button when a method running

private void AddMyScrollEventHandlers()
{
VScrollBar vScrollBar1 = new VScrollBar();
}
private void button1_Click(object sender, EventArgs e)
{
while (true)
{
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
break;
}
System.Threading.Thread.Sleep(200);
}
}
private void button2_Click(object sender, EventArgs e)
{
// vScrollBar1.Scroll
}
I am new in C#. I was working on scroll. What I wanted here is, if anyone click button1 then scroll automatically move to the end and I wanted to show gradual value in label1. Also when someone click button2 scrolling stop.
Now the problem is label1 do not show gradual change in value. It shows value once when the scrolling stop.
Also when scrolling continue i,e when while loop is working I can not click on button2. Actually I can not click on the form even.
Someone please give me some idea how to do this.
This happens because the thread that is performing the task is busy, and it's the same thread that updates the UI. You can use a multithreading solution. Take a look at
BackgroundWorker
All the UI events run in the main thread of the application, so the application can only process one event at a time. When the application is processing an event, no other event will be processed.
Since you are doing a UI related work periodically, the best option is to use the Timer class:
Drop Timer from the toolbox into the form.
In the properties window, set the interval to 200.
Double click the timer object to create the Tick event handler.
Put this code in the newly created timer1_Tick method:
if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
vScrollBar1.Value = vScrollBar1.Value + 1;
label1.Text = vScrollBar1.Value.ToString();
}
else
{
timer1.Stop();
}
Change your methods as below:
private void AddMyScrollEventHandlers()
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
Now you're done.
I would recommend using BackgroundWorker control, as suggested by Agustin Meriles. However, one more important thing to note is that You should use Control.Invoke(...) method to update controls from another thread.
I've modified Your code, tested it in a sample application and it seems to work correctly.
First, add a new BackgroundWorker control to Your form and assign backgroundWorker1_DoWork to its DoWork event.
Then, You can use the code below:
private void button1_Click(object sender, EventArgs e)
{
//code from here is moved to BackgroundWorker control
backgroundWorker1.RunWorkerAsync();
}
private void button2_Click(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//while (true)
//the condition directly in the while looks more clear to me
while (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
{
//update controls using Invoke method and anonymous functions
vScrollBar1.Invoke((MethodInvoker)delegate() { vScrollBar1.Value += 1; });
label1.Invoke((MethodInvoker)delegate() { label1.Text = vScrollBar1.Value.ToString(); });
//when called inside BackgroundWorker, this sleeps the background thread,
//so UI should be responsive now
System.Threading.Thread.Sleep(200);
}
}
If You have any problems when using this code, please let me know.
Update
As mentioned in the comments, You could also use ProgressChanged event of the BackgroundWorker. It requires some more changes in the code, but is more suitable in this case. You can find some information about it here: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx.
If You are not going to add any other code with more processing in the while loop, You can also use Timer control, as suggested by MD.Unicorn in his answer.

Categories

Resources