I have one main form that starts on program in program.cs as Application.Run(new Form1());. It opens object of 2 different forms as:
Form2 obj1 = new Form2();
obj2.Show();
Form3 obj2 = new Form3();
obj3.Show();
Each form has Thread.Sleep(10000) code but the problem is that on one's Thread.Sleep execution, whole programs sleeps. I thought if one form's Thread.Sleep runs, it will not stop other form and will not affect those.
All GUI components run on a single GUI thread therefore if you sleep that thread everything running on that thread sleeps, which in your case means all of your forms.
If you need a particular form to wait for something to happen then there are various ways of doing that, however, you need to be a bit more clear in your question as to what exactly it is you are waiting for.
Related
I'm Trying to develop an app for an old handheld device running .Net 3.5 Win CE 5 however I cannot seem to get over a basic hurdle switching forms!!
I started using
Application.Run(new frm_class());
but this started crashing after opening any more then 2 forms.
I then tried.
this.hide();
frm_class frm = new frm_class();
frm.show();
then just ended up being a constant loop of loading the form
then I seen someone wrote a very simple class to handle this.
public static void switchForm(Form newForm, Form oldform)
{
newForm.Show();
oldform.Hide();
oldform.Dispose();
}
call via
frm_class frm = new frm_class();
switchform(frm,this);
which shuts the app down when loading the second form.
This seems so stupid but I cannot find out a way of just navigating through simple forms ie close this form then open this one or vice versa!!
can anyone help?
Application.Run(new frm_class()); will start a message loop and makes the specified form visible and waits untill it is closed. Once the specified form closes, the message loop terminates.
oldform.Dispose(); will dispose (and close) the form, not hide it.
Your second solution seems like the one you should take, which shouldn't loop. Make sure the code isn't in the constructor or form_load event if you're creating the same form again. Can you post the code surrounding this?
You could also remove the new frm_class() argument from Application.Run(). Which will create a constant running message loop. Just don't forget to call Application.Exit() at some point.
You should make sure the form is made visible before the parameterless Application.Run() because the execution inside this codeblock wont continue untill Application.Exit() is called from inside your form.
frm_class frm = new frm_class();
frm.Show();
Application.Run();
// Some button or event inside the form should be executing the exit call:
Application.Exit();
I have a form with labels A, B and C. In static void Main(), I say:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 form1 = new Form1();
Application.Run(form1);
Form1 constructor calls
InitializeComponent();
updateForm();
where updateForm reads a log ((FtpWebRequest)WebRequest) from a remote machine and updates the labels appropriately.
I would like to constantly update the form, because the remote log file is changing every few minutes.
I tried calling form1.updateLog() in while(true) loop in the main method, but the form doesn't refresh. Also, form1.Refresh() doesn't seem to work.
Any hints?
Thanks.
When you're doing that in a loop then most likely on the UI thread. This means that you constantly tell the Form to repaint yet don't give it time or an opportunity to do so (remember: you're blocking the thread on which it would do that).
Instead use a timer and refresh from there, e.g. every 100 ms or so.
Hi I have a method like below:
void Foo
{
MethodInvoker method=delegate{
frm2 frm=new frm2();
frm.show();
}
and I have a datagridview control inside this form which does a heavy loading from DB and loads data inside this datagridview in frm2.
the problem is that the main thread(form1 thread) is freezed at time when the data is attached to datagridview in frm2.Why is this happening.
I created two different projects and separate frm2 and form1 in these 2 projects and the results are ok and no freeze is happening to none of them.
Well, I think there is one single thread for any UI manipulation in WinForms.
If you are doing DB retrieval within Form constructor, then this is performed in the UI thread, and all forms freeze.
You should create a new thread to fetch your data from DB and set it later in the UI in the UI thread.
I want to have a loading form showing up while the main app connects to db and fetching initial data. Because this can take up 5-10 secs I want to inform the user that something is happening.
This is what I have come up with:
frmStart _frmStart = new frmStart();
Thread t = new Thread(() => _frmStart.ShowDialog());
t.Start();
objDAL = new DBManager();
objDAL.conSTR = Properties.Settings.Default.conDEFAULT;
PrepareForm();
t.Abort();
Is this the best way?
No, this doesn't solve the frozen UI problem, it merely papers it over. Imperfectly at that, the dialog's parent is the desktop and can easily appear underneath the frozen window and thus not be visible at all. And the dialog isn't modal to the regular windows since it runs on another thread. The failure mode when the user starts clicking on the non-responsive window is very ugly, those clicks all get dispatched when the UI thread comes back alive.
There are workarounds for that (you'd have to pinvoke SetParent and disable the main windows yourself) but that's just solving the wrong problem. You should never let the UI thread block for more than a second. Use a BackgroundWorker to do the heavy lifting, update the form with the query results in the RunWorkerCompleted event handler.
If you are using WinForms you may want to take a look at this A Pretty Good Splash Screen in C#. If you are using WPF you could take a look at this Implement Splash Screen with WPF.
I am displaying dialog on the main form, now one for loop is working behind but when that dialog will displayed code execution will be stopped, but I don't want to let stop the execution of the code, is any other any way to do that ?
EDIT: I am using now thread to do that and my code is like
Thread t;
private void StartParsingByLoop()
{
t = new Thread(new ThreadStart(RunProgress));
t.Start();
for (int i = 0; i < dialog.FileNames.Length; i++)
{
cNoteToParsed.AllContrctNotesFilePath.Add(dialog.FileNames[i].ToString());
}
cNoteToParsed.ParseContractNote();
if (cNoteToParsed.NOfContrctNoteParsed > 0)
LoadTransactionsInDataGridView();
t.Abort();
}
private void RunProgress()
{
frmProgress progressForImportingTran = new frmProgress("Importing Transactions", "ok");
progressForImportingTran.ShowDialog();
}
Now I have problem is that the dialog that shows the progress does not behave like dialog and gives access of the main form and if we try to access the main form then dialog goes to hide. And I dont want to make the dialog be hide.
You can let a different thread handle the loop.
Response to edit: Can you provide more details, perhaps some code? what is the loop doing? what form do you display?
(this answer is based on the assumption that we are taking about a winforms app)
Show the form using the Show method, rather than ShowDialog. By passing a reference to the main form, the dialog will stay on top of the main form even if it is not modal:
TheDialog dialog = new TheDialog();
dialog.Show(this);
Note though that the user can still interact with the controls on the main form, so you might want to disable some controls, depending on your scenario.
You state in your question that there are requirements that prevent you from using threading for this. This kind of requirement strikes me as odd, and it is a pity because this is one of the typical scenarios when you would want to use some sort of asynchronous construct. By performing heavy work on the UI thread, you get some drawbacks, including:
The UI will not be responsive - if you want to allow the user to cancel the work by clicking a button, that will be tricky to achieve in a robust manner.
The UI will not redraw properly since the UI thread is busy performing other work.
Do not use ShowDialog() but Show() to display the dialog windows. Show() will immediately return to the caller whereas ShowDialog() will hold the execution. Note that when using Show() your dialogs won't be modal anymore.
OK, so you don't need modal dialog, you need a mechanism for your user not to be able to select your main form while processing is enabled.
Modal dialog doesn't mean that execution is stopped - it just happens somewhere else.
There are several methods to do this, and you ruled out new thread creation (don't know why, it would solve it elegantly). If don't use thread, you'll have another problem - your processing should be done in CHUNKS and every little while you'll have to do something like Application.DoEvents() to enable your application to process messages and not be frozen to the user.
So, if you can create a method in the main form that shows your 'please wait' dialog which will perform some work and later do some more until is finished, you can do this:
create a new form (wait dialog)
start a timer inside of it and wire timer to the PARENT form
timer interval should be 1
ShowDialog() the form
on timer event do small amount of work (don't allow it to go more then 1/10 of seconds)
Can you do that?
Anyway:
task can't be split into small workable pieces
you can't use threads
you want your UI to be responsive
PICK 2. You can't have all 3 in Winforms.