C# - Manually closing a forms application - c#

I would like to know the appropriate way to completely terminate a Forms application. I open the form in the standard way using the code:
namespace History
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new DisplayHistory());
}
}
}
...and here is a barebones version of the DisplayHistory function with the various things I've tried to terminate the application commented out. The first two cause an unhandled exception stating that I cannot access a disposed object. The third one has no effect at all, and the fourth one won't compile at all because I get an error saying that "Application does not contain a definition for Current":
public DisplayHistory()
{
InitializeComponent();
// this.Close();
// Close();
// Application.Exit();
// Application.Current.Shutdown();
}

Instead of trying to close it in constructor, it's better not to open the form.
But if you really want to close the form in constructor based on some condition, you can subscribe for Load event before InitializeComponent in code and close the form using this.Close()
:
public Form1()
{
if (some criteria)
{
this.Load += (sender, e) => { this.Close(); };
}
return;
InitializeComponent();
}
To close an application normally, you can call below codes anywhere except constructor of form:
this.Close();
Application.Exit();
To force the application to stop, or close it abnormally, you can call Environment.Exit anywhere including the form constructor:
Environment.Exit(1);

Related

C# app stays in task manager after closing [duplicate]

why The process still on Windows Task list manager after close programme ?
i use login Form.cs
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Login());
}
after the user succesuly login, i redirect to another Masterpage
this.Hide();
Main_Usr oMainUsr = new Main_Usr();
oMainUsr.Visible = true;
my pseudo master page like this:
public Main_Usr()
{
InitializeComponent();
this.IsMdiContainer = true;
}
when i close the masterpage, The process still on Windows Task list manager.
But when i close the login page, it kill the process on Windows Task list manager.
is that mean because i just hide le login page ?
must i close all window to realy quit/kill the process ?
Thanks you in advance,
Stev
In winforms process will be killed, when main application form is closed. Main application form is one specified in Application.Run call. In your case it is Login form:
Application.Run(new Login());
To close form you should call Close method. When you call Hide or set Visibility to false, form stays in memory. It just becomes hidden from user.
So, to achieve desired functionality you should change main application form to Main_Usr:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Main_Usr()); // change main form
}
Then subscribe to Load event of Main_User form. And in the event handler do following:
private void Main_User_Load(object sender, EventArgs e)
{
using (var loginForm = new Login())
{
Hide(); // hide main form
if (loginForm.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
Close(); // close main form and kill process
return;
}
Show(); // show main form if user logged in successfully
}
}
UPDATE: You can do this all in Main method, like this way
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using(var loginForm = new Login())
if (loginForm.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
Application.Run(new Main_Usr()); // change main form
}
but usually I don't hide main form and show it below login form. So, in this case you should use Load event handler. It's up to you.
BTW there is no masterpages and pages in winforms. This all is for ASP.NET. Here you have forms :)
Also consider naming like LoginForm, MainForm etc.
This is because the application message loop is associated with your Login form (Application.Run(new Login()) does this), so you need to close the form which started the application to end the process.
Alternatively, you could just call LoginForm.Show(), before Application.Run, store credentials somewhere and then call Application.Run(new Main_Usr)
Because Login is the last form of the application to close, you load Main_User only after that - even if Login is hidden it's still actually there. Windows Forms applications are by default configured to exit when the last form closes.
this.Hide()
doesn`t kill the window.
So it remains hidden and process remains in memory.
this.Close() closes the window and removes its object from memory.
It is better to do something like this:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var l = new Login();
l.ShowDialog();
if(l.Passed)
Application.Run(new Login());
}
And implement Passed property inside login window.
By the way, do you have any multithreading inside?
It is another source of errors of this type.
i found it, i just use the dizlog.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Login oLogin = new Login();
oLogin.ShowDialog();
Application.Run(new Main_Usr());
}
i follow code the #lazyberezovsky and add this on my Login.cs
private void simpleButton_Valider_Click(object sender, EventArgs e)
{
.....
DialogResult = DialogResult.OK;
return;
.....
}

Destructor vs App.Current.Exit vs All other exit handlers

Im having an issue where i need to get my Classes to run a piece of code on exit.
Basically the code writes the Property's and Parameters to an XML file so they can be sent to the programmer to replicate the same settings as the client.
so i have created code like this on each of my classes.
~WorkspaceViewModel()
{
this.Save("Workspace");
}
my problem is that i cannot find a handler that will run before this destructor.
i have tried the following
//App.Current.Exit += new System.Windows.ExitEventHandler(ProgramExit);
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(ProgramExit);
//App.Current.MainWindow.Closed += new EventHandler(ProgramExit);
//App.Current.Windows[0].Closed += new EventHandler(ProgramExit);
//AppDomain.CurrentDomain.DomainUnload += new EventHandler(ProgramExit);
//App.Current.MainWindow.Unloaded += new System.Windows.RoutedEventHandler(ProgramExit);
//System.Windows.Forms.Application.ApplicationExit += new EventHandler(ProgramExit);
//System.Windows.Application.Current.Exit += new System.Windows.ExitEventHandler(ProgramExit);
And saw something online about modifying the App class so i did this.
public partial class App : System.Windows.Application
{
public void OnExit()
{
this.OnExit();
}
public void App_Exit(Object sender, System.Windows.ExitEventArgs Args)
{
//Somelogic here
}
public App()
{
this.Exit += new System.Windows.ExitEventHandler(App_Exit);
}
}
could someone please help.
Are you using Windows Forms? If so, you can use the Closing event of the form. More reading: Form.Closing Event
Definition:
Occurs when the form is closing.
Example:
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if(MessageBox.Show("Do you want to exit?", "Your app title", MessageBoxButtons.YesNo) == DialogResult.No)
{
e.Cancel = true;
// cancel the closing
}
//otherwise the application will exit
}
You don't really need the if-statement, you can just call the Save method in this event and let the application exit afterwards.
You could do it this way (pseudocode)
Init();
window.Show();
Deinit();
You explicitly run initializers on application start and deinitiliazer on exit.
And in WPF it's done by using Application events, overrides or by a trick (setting Page build action for App.xml). In your implementation, you can't have constructor declared, because it's already generated (file App.g.i.cs). You can use application startup event though or simply set events in xaml.
As it turns out. all i needed to do was create a destructor on the App Class like this
public partial class App : Application
{
~App()
{
Administration.Model.DataBaseModel.GlobalCatalogue.ToFile();
}
}
Not really sure this is the best approach tho
Im still open to better ideas however.. thank you all.

Run two winform windows simultaneously

I have two C# winform (.NET 4.0) forms that each run separate but similar automated tasks continuously. Separate in that they are distinct processes/workflows, but similar enough in how they operate to share the same resources (methods, data models, assemblies, etc) in the project.
Both forms are complete, but now I'm not sure how to run the program so that each window opens on launch and runs independently. The program will be "always-on" when deployed.
This might seem a little basic, but most of my development experience has been web applications. Threading/etc is still a little foreign to me. I've researched but most of the answers I've found relate to user interaction and sequential use cases -- this will just be one system continuously running two distinct processes, which will need to interact with the world independently.
Potential solutions I've found might involve multi-threading, or maybe some kind of MDI, or a few folks have suggested the DockPanelSuite (although being in a super-corporate environment, downloading third party files is easier said than done).
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Rather than specifying frmOne or frmTwo,
// load both winforms and keep them running.
Application.Run(new frmOne());
}
}
You can create a new ApplicationContext to represent multiple forms:
public class MultiFormContext : ApplicationContext
{
private int openForms;
public MultiFormContext(params Form[] forms)
{
openForms = forms.Length;
foreach (var form in forms)
{
form.FormClosed += (s, args) =>
{
//When we have closed the last of the "starting" forms,
//end the program.
if (Interlocked.Decrement(ref openForms) == 0)
ExitThread();
};
form.Show();
}
}
}
Using that you can now write:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MultiFormContext(new Form1(), new Form2()));
If you really need two windows/forms to run on two separate UI threads, you could do something like this:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var thread = new Thread(ThreadStart);
// allow UI with ApartmentState.STA though [STAThread] above should give that to you
thread.TrySetApartmentState(ApartmentState.STA);
thread.Start();
Application.Run(new frmOne());
}
private static void ThreadStart()
{
Application.Run(new frmTwo()); // <-- other form started on its own UI thread
}
}
Assumption
You do not need the two different processes, you are only using the 2 processes because you want to have the two different forms and want to be able to keep the application running until both forms are exited.
Another solution
Rely on the Form.Closed event mechanism. You can add an eventhandler which allows you to specify what to do when a form closes. E.g. exit the application when both forms are closed.
In terms of some code
public Form1()
{
InitializeComponent();
_form2 = new Form2();
_form2.Show(this);
this.Closed += Form1Closed;
_form2.Closed += Form2Closed;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
Form1Closed(this, new EventArgs());
base.OnFormClosing(e);
}
private void Form1Closed(object sender, EventArgs eventArgs)
{
form1IsClosed = true;
TryExitApplication();
}
private void Form2Closed(object sender, EventArgs eventArgs)
{
_form2IsClosed = true;
TryExitApplication();
}
private void TryExitApplication()
{
if (form1IsClosed && _form2IsClosed)
{
Dispose();
Application.Exit();
}
}
Note that this should be refactored to make it a better solution.
UPDATE
The comments provided by Servy made my revise this "supposed to be simple solution", which pointed out that his solution is way better then this solution. Since I am supported to leave the answer I will use this answer I will also address the issues that start arising when going for this solution:
cancelling close events
rerouting from one event to another
force calling Dispose.
as Servy pointed out: maintenance unfriendly (state to check which form is closed)

I have a system task tray application - Can I close the main form instead of just hiding it?

I have an application that has a main form and a system task tray icon. In the designer of the main form, I dragged the TrayIcon control on the form, so it is a child of the main form.
At this point, when the user presses the close button on the main form, it actually just hides it so that the application wont terminate, unless the user right clicks the TrayIcon and clicks exit. But, the main form has a lot of controls and resources, and when the main form is hidden, it still uses memory for those resources. My goal is to actually dispose of form so it doesn't take up that memory while it is not being used.
Unless I am mistaken, and when the main form is hidden it doesn't take up that memory anymore, but I don't think that is the case.
I'm no expert on memory, I may even be completely mistaken on how memory management works, and thus this question is invalid.
Anyways, if I am correct in that when the main form is only hidden it still takes up memory that can be freed by fully closing the form, is there a way for me to actually close the main form without the application terminating? If so, I would need to create the TrayIcon with code in the Program class instead of in the class of the main form, correct?
No, that's certainly not necessary. It is encouraged by the convenience of the designer but you can easily create an application that only creates a window on demand. You'll have to write code instead. It doesn't take a heckofalot, there's a sample app with basic functionality. Edit the Program.cs file and make it look similar to this (icon required, I called it "SampleIcon"):
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var cms = new ContextMenuStrip();
cms.Items.Add("Show", null, ShowForm);
cms.Items.Add("Exit", null, ExitProgram);
var ni = new NotifyIcon();
ni.Icon = Properties.Resources.SampleIcon;
ni.ContextMenuStrip = cms;
ni.Visible = true;
Application.Run();
ni.Dispose();
}
private static void ShowForm(object sender, EventArgs e) {
// Ensure the window acts like a singleton
if (MainWindow == null) {
MainWindow = new Form1();
MainWindow.FormClosed += delegate { MainWindow = null; };
MainWindow.Show();
}
else {
MainWindow.WindowState = FormWindowState.Normal;
MainWindow.BringToFront();
}
}
private static void ExitProgram(object sender, EventArgs e) {
Application.ExitThread();
}
private static Form MainWindow;
}

c# Windows form application forms problem

I have a c# windows form app which contains several forms.
Generally, for example, in form1, I create a instance of form2 and then
form1.hide();
form2.show();
But sometimes I want the previous form to show and dispose current form. How can I call the previous form?
Thanks in advance.
To answer your question, you need to maintain references in your views to each other. While this might work it's messy and error prone. It sounds like all your control logic is probably contained within your form class code and I would suggest moving away from that and separate your concerns.
Solving your form management issues becomes very simple if you create a controller class that, at a minimum, manages the creation and disposal of your forms in whatever way you see fit.
So your code sample would actually be launched from a controller class as something like:
public class FormsController
{
private Form form1 = new Form();
private Form form2 = new Form();
public void SwitchForms()
{
form1.hide();
form2.show();
}
}
For further edification checkout the MVC architectural pattern for cleanly working with data, biz logic and UI.
You might consider extending Form to include some properties/fields that allow you to access other forms. the Form class can be inherited from just like most other .Net classes.
You may also consider doing some of that management in the Program.cs file that is part of you project, if neither form is really supposed to be a child of the other.
If you inherit a new class for your form1 from Form and add a method like closeSecondForm you can have it close and dispose the second form.
There are probably a bunch of different ways to solve the issue. These are just a few.
If you set the new form's Owner to a reference to the current form, you can reference that Owner from the new form. You could also subscribe to the new form's Closed() event from the old form, with code to dispose it (though the form can dispose itself by overriding OnClosed, if it doesn't happen there anyway).
This logic should be handled in Program.cs. The Main() method initializes Form1. You want to take control there instead of passing control to the form.
Example:
static class Program
{
internal static Form1 MyForm1;
internal static Form2 MyForm2;
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
// Initialize Form1
MyForm1 = new Form1();
MyForm1.FormClosing += new FormClosingEventHandler(MyForm1_FormClosing);
// You may want to initialize Form2 on-demand instead of up front like here.
MyForm2 = new Form1();
MyForm2.FormClosing += new FormClosingEventHandler(MyForm2_FormClosing);
// Show Form1 first
MyForm1.Show();
// Now we need to occupy the thread so it won't exit the app. This is normally the job of Application.Run.
// An alternative to this is to have a third form you pass on control to.
while (true)
{
Application.DoEvents();
System.Threading.Thread.Sleep(10);
}
}
static void MyForm1_FormClosing(object sender, FormClosingEventArgs e)
{
// Do something, for example show Form2
MyForm2.Show();
// EXAMPLE: We only want to hide it?
e.Cancel = true;
MyForm1.Visible = false;
}
static void MyForm2_FormClosing(object sender, FormClosingEventArgs e)
{
// Do something, for example show Form1
MyForm1.Show();
// EXAMPLE: We only want to hide it?
e.Cancel = true;
MyForm2.Visible = false;
}
}
Since Program is static you can access MyForm1 and MyForm2 anywhere in that project by:
Program.MyForm1.Show();
Program.MyForm2.Hide();
If you plan to have many forms/complex logic I suggest moving this to a separate class. Also consider using a single form and rotate user controls inside it instead.
Form2 myform = new Form2();
myform.show();
this.hide();
You could do this in form1:
...
var form2 = new form2();
form2.Closing += (form2_Closing);
this.hide();
form2.show();
...
private void form2_Closing(object sender, System.EventArgs e)
{
this.show();
}

Categories