Show (popup) Dialog Form using Background Worker? - c#

I must sleep my main thred 5 times, pausing 10 seconds each time for a certain task.
Problem is that my main windows form freezes during the duration. So, I'd like to show a pop-up window wich is not frozen.
I've added a background worker to my main form:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// ... how do I involve this?
}
When I push a button on my main form it does this:
BussyWindow bussyWindow = new BussyWindow();
bussyWindow.ShowDialog();
And then my main form goes into a loop for about 50 seconds.
I've tried:
BackgroundWorker bw = new BackgroundWorker();
bw.RunWorkerAsync(bussyWindow);
I'm stuck! What to try next?

You don't need another form if you are using BackgroundWorker,try this:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerAsync();
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
// do your work here
}
Your work will be done asynchronously..

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"));

C# winforms progress bar marquee animated during sleep, but not during work

I implemented a windows form in c# with a progress bar in marquee style and a backgroudworker to do a job. The progress bar animation is working correctly when the backgroundworker sleeps, but it hangs when the backgroundworker starts to do something. Does anyone know what I am doing wrong?
Thanks in advance for your answers.
Here is my code:
public FormProgressBarMarquee()
{
InitializeComponent();
this.progressBar1.Style = ProgressBarStyle.Marquee;
this.progressBar1.MarqueeAnimationSpeed = 50;
Shown += new EventHandler(FormProgressBar_Shown);
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_Completed);
}
void FormProgressBar_Shown(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
System.Threading.Thread.Sleep(10000);
// the progress bar animation works correctly
longtimerunningprocess.start();
// the progress bar animation stops
}
void backgroundWorker1_Completed(object sender, RunWorkerCompletedEventArgs e)
{
Debug.Print(" :: FormProgressBar :: ...Pack And Go loaded, close form...");
this.DialogResult = DialogResult.OK;
this.Close();
}
I could finally solve the problem myself. Thanks anyway for the comment #digvijay which put me on the right track.
The program I am writing is part of a class library. longtimerunningprocess is part of the main program and is executed in the main UI thread.
Although I always try to keep the splash screen in the main UI thread and put the non UI work into a separate thread using a backgroundworker, this time I had to put the splash screen in a separate thread.
To do so, I used this suggestion:
https://stackoverflow.com/a/48946

How to show a form from a thread different than the ApplicationContext thread

I am trying to make a windows application that start in the system tray as a NotifyIcon and then shows some forms based on events and user input.
I'm using Visual Studio 2013
So what I did is delete the default form VS creates and delete the Application.run() from Program.cs and did Application.run(new MyApplicationContext()) where MyApplicationContext is a class that extends ApplicationContext where I initialize and show the NotifyIcon
Then I made a woker thread that queries a database for information and tries to show that information in a NotificationForm that I created.
If I do something like this in the woker thread code:
NotificationForm form = new form();
form.Top = // change the location;
form.show();
The notification shows in the default position, and any UI element on it appears transparent and I can see-through to desktop
But if I call Application.run(form) in the worker thread the form works right and shows in the right position, but it blocks my worker thread.
If I had a Form I would call Invoke on that Form. But what am I supposed to do in my case?
EDIT: As a workaround I initiated a Form called parentForm in the MyApplicationContext then called show on it then made it invisible. And then I invoke from that. But it seems a dirty work around and not the right one;
BackgroundWorker _backgroundWorker;
private void Init()
{
_backgroundWorker = new BackgroundWorker();
_backgroundWorker.WorkerReportsProgress = true;
_backgroundWorker.ProgressChanged += _backgroundWorker_ProgressChanged;
_backgroundWorker.DoWork += _backgroundWorker_DoWork;
_backgroundWorker.RunWorkerAsync();
}
private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker backgroundWorker = sender as BackgroundWorker;
Thread.Sleep(5000);
backgroundWorker.ReportProgress(0);
Thread.Sleep(5000);
backgroundWorker.ReportProgress(10);
}
private void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Form form = new Form();
form.Text = "Percentage:" + e.ProgressPercentage.ToString();
form.Show();
}
I didn't test it, but it might works like that.

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.

Progressbar for long running function WP7 C#

I am writing a sudoku solver app. The calculation time of the solver in certain cases can exceed 3 seconds, which would require a progress bar.
so my code:
private void solveButton_Click(object sender, RoutedEventArgs e)
{
progressBar1.Visibility = Visibility.Visible;
progressBar1.IsIndeterminate = true;
mySolver.Solve(initialValue)
progressBar1.Visilibity=Visilibity.collapsed;
progressBar1.IsIndeterminate = false;
}
The code here is a condensed version of my actual code. This code doesn't work, as the progress bar does not appear at all. It seems to me that the UI updates only after event is finised executed. If I didn't hide the progressbar after the solver step, the progressBar appears after the sudoku is solved. Replacing the solver with thread.sleep(1000) also results in the same UI update.
thanks for your help.
You should start the solver on a separate thread. That way the user interface thread can keep working on user interface objects even during the solving process, which allows your progress bar to be drawn on the screen and updated.
Problem is that your UI thread is not getting free in between to display the progress bar
You need to use the background worker to solve the problem and in the main UI thread you should display the progress bar
private void solveButton_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
bg.RunWorkerAsync();
progressBar1.Visibility = Visibility.Visible;
progressBar1.IsIndeterminate = true;
}
void DoWork(Object sender, DoWorkEventArgs args)
{
mySolver.Solve(initialValue)
}
void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs args)
{
// this method will be called once background worker has completed it's task
progressBar1.Visilibity=Visilibity.collapsed;
progressBar1.IsIndeterminate = false
}
Technically the code works fine, you just wrote the wrong code.
Your solver is running on the UI thread so it never has a chance to draw the progress bar before you hide it again. You need to spawn a thread (or use a background worker) to free up the UI thread so it can draw your progress bar.
I don't know too much about WP7 but with winforms if you have a long running function it needs to be run on a different thread than the UI.
Is BackgroundWorker available to you on WP7? you can update the bar on the ProgressChanged event and change the viability on the RunWorkerCompleted event
private void solveButton_Click(object sender, RoutedEventArgs e)
{
progressBar1.Visibility = Visibility.Visible;
progressBar1.IsIndeterminate = true;
solveButton.Enabled = false; //I reccomend this so the button can't be pressed twice.
BackgroundWoker bw = new BackgroundWorker();
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.DoWork += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerAsync()
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
mySolver.Solve(initialValue, e)
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
{
//Handle any exceptions that happened in the background worker.
}
progressBar1.Visilibity=Visilibity.collapsed;
progressBar1.IsIndeterminate = false;
solveButton.Enabled = true;
((IDisposable)sender).Dispose();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
//inside mySolver
void Solve(somthing initialValue, DoWorkEventArgs e)
{
//Your solver work
e.ReportProgress(progress); //a int from 0-100
//more solver work
}
If you still want to run it on the UI Thread (which i wouldn't recommend!!) you can use the progressbar from the WP7 Toolkit that was released yesterday. It contains a progressbar that will work while your UI Thread is blocked.

Categories

Resources