Request using BackgroundWorker never seems to complete - c#

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.

Related

Cef browser form is coming up blank after Form.Hide(); / Form.Show();

I am using cefsharp on a winforms project to display a browser form on top of my main form, both of them inside and MDIParent. When i am calling the browser form it draws correctly navigating to the requested site. In the form i have a button to hide it, so the main form comes back up. When I request again for the browser form to .Show() it comes up blank.
public partial class MDIParent1 : Form
{
//this is the browser form
static Eztvit ezForm = new Eztvit();
public MDIParent1()
{
InitializeComponent();
setStatusText("Initializing...");
//this is the main form
comparisonForm cForm = new comparisonForm();
cForm.MdiParent = this;
cForm.Show();
cForm.Dock = DockStyle.Fill;
setStatusText("Ready");
ezForm.MdiParent = this;
ezForm.Dock = DockStyle.Fill;
}
private void button1_Click(object sender, EventArgs e)
{
ezForm.Show();
}
}
And in the browser form i got this button:
private void backBtn_Click(object sender, EventArgs e)
{
this.Hide();
}
Thank you in advance for your contributions.
I had this problem when reshowing from the same UI thread by using Invoke/BeginInvoke. The cef browser thread seems to deadlock and no other calls will be honored (like ShowDevTools or change url).
Your case is similar in that the Hide() call is being executed on the UI thread (coming from the button handler) so I would suggest to try putting that Hide() call in a separate Task or Thread.

How to launch method when window got focus again in WPF?

My app is multi-window, here is quickly how it works:
In main window I have a list of items, when I click on one, it opens another window where I can modify it. When I close that window, I want main window to refresh its content. I've tried many event handlers including GotFocus() but it doesn't want to launch my method to refresh the list. Any advise?
If you want something to happen when the other window is closed, you can subscribe to its closed event. This will fire when the windows is closed.
private void Button_Click(object sender, RoutedEventArgs e)
{
var wnd = new Window1();
wnd.Closed += wnd_Closed;
wnd.Show();
}
void wnd_Closed(object sender, EventArgs e)
{
MessageBox.Show("Closed");
}

Closing main app while form is running a thread

I have a C# windows application in which I create an instance of a some class, in which it has a member which is a window form and this form has a button that when I click it I open a new form that can run a worker thread, let's say:
public static void Main()
{
MyClass mc = new MyClass();
mc.ShowForm();
}
in MyClass.cs:
public void ShowForm()
{
MyFirstForm firstForm = new MyFirstForm();
firstForm.Show();
}
in MyFirstForm.cs:
private void myButton_Click(object sender, EventArgs e)
{
MySecondForm secondForm = new MySecondForm();
secondForm.Show();
}
in MySecondForm.cs:
private void startButton_Click(object sender, EventArgs e)
{
var worker = new Thread(StartWork);
worker.Start();
}
private void stopButton_Click(object sender, EventArgs e)
{
m_stopped = true;
}
private void StartWork()
{
while(!m_stopped)
{
//work...
}
}
When I run my app, clicks myButton, then click startButton, and then exit my app (I have a tray Icon that when clicked to exit, call base.Shutdown() ), the second form stays hanging and non responsive.
My original question was, what is the best way to notify the second form that it should close and stop the running thread, but during writing this post I noticed that I can use Task.Factory.StartNew(StartWork); and when I tried it, it worked without a hitch.
So now I have another question which is why is this happening?
I tried registering to Closing , Closed , FormClosing events and setting m_stopped = true but they were not getting called.
EDIT:
As #drf suggested the thread is a foreground thread hence the app is blocked while it runs, so adding:
worker.IsBackground = true;
fixed it.
Your thread is currently a foreground thread which will prevent the process from exiting until the thread finishes. http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.110).aspx
Change your thread startup code to this:
private void startButton_Click(object sender, EventArgs e)
{
var worker = new Thread(StartWork);
worker.IsBackground = true;
worker.Start();
}
I think for closing application you should use Application.Exit Method:
It informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed.
Also you could track FormClosing event of each form. Check if Thread.IsAlive then Thread.Abort() or cancel closing.

cancel process by clicking a button

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.

Dispose of dialogwindow in backgroundworker

i'm loading screen in backgroundworker:
private void LSLoadingScreen(object sender, DoWorkEventArgs e)
{
LoadingScreen ls = new LoadingScreen(this.timerStart);
ls.ShowDialog();
while (LoadingScreen.CancellationPending)
{
ls.Dispose();
LoadingScreen.Dispose();
}
but my loadingScreen doesn't dispose when i use this code in other function:
LoadingScreen.CancelAsync();
timerStart = false;
LoadingScreen.Dispose();
How to dispose it properly?
Firstly, ShowDialog() will prevent the rest of the code executing until the dialog is closed - which you are never doing.
Even when it does close, it will evaluate the while loop (which will most likely be false so skipped) and then your backgroundworker will be finished.
If all you are doing is showing a dialog then I would just do this on the main thread, and have your loading process on the background worker..
Fire background worker (which does loading code)
Show your loading dialog
On BackgroundWorkerCompleted event, close your loading dialog
Try to get all your UI elements in the main UI thread.
Hope that helps
EDIT:
Based on your comment...
public partial class MainForm:Form
{
LoadingScreen ls;
public MainForm()
{
}
public void StartLoad()
{
ls = new LoadingScreen(this.timerStart);
backgroundWorker.RunWorkerAsync();
ls.Show();
}
void backgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
//Loading code goes here
}
void BackgroundWorkerMainRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(ls != null)
ls.Close();
}
}

Categories

Resources