Application won't end VideoStreams and Exit - c#

I've got an application what's working with two video streams.
When the form is being closed, it runs this function:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (FinalVideoDevice.IsRunning) { FinalVideoDevice.Stop(); }
if (streamMJPEG.IsRunning) { streamMJPEG.Stop(); }
Application.Exit();
}
But in reality it doesn't kill the application, only hides the form, but still is seen from TaskManager/Processes.
Any ideas what I might be doing wrong?
Thanks!

Assuming you are in Windows Forms you can call Application.ExitThread();
in general one of the reasons why you still see the process in TaskManager could be that you still have some background / worker threads active.
Roger check this question/answers as well: Application.Exit

Related

WinForms switching between forms memory problem [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I currently have 3 forms, a main menu, form 2 and form 3. Is there an optimised way of opening forms (and closing them) as when I switch between them they are taking memory up and I can quickly get to a few GBs usage switching between them over a few minutes.
private void button2_Click(object sender, EventArgs e)
{
this.Hide();
NewForm NewForm = new NewForm();
NewForm.ShowDialog();
this.Close();
this.Dispose();
I've found if comment out this.Hide() my forms aren't actually closing. How can I close the forms when the new one is opened?
Presumably, you're using ShowDialog() to keep the app from exiting when the original, main form is closed?
A different approach would be to use the overload of Application.Run that receives an ApplicationContext.
Then you could write your own "application context" and tell the application to only exit when there are no more forms open. This will allow you to switch from ShowDialog() to Show(). The small change means the old form will be disposed of since code execution continues after Show().
Back in our ApplicationContext class, we can wire up the Idle event and check the count of open forms in Application.OpenForms, letting us know when all forms have been closed and it is time to shut down the application.
So your "program.cs", would change to:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyAppContext(new Form1()));
}
}
public class MyAppContext : ApplicationContext
{
public MyAppContext(Form startingForm)
{
startingForm.Show();
Application.Idle += Application_Idle;
}
private void Application_Idle(object sender, EventArgs e)
{
if (Application.OpenForms.Count == 0)
{
Application.Exit();
}
}
}
Now, whenever you want to switch forms, just make sure to Show() the new form before you Dispose() of the current one:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show(); // make sure you "Show()" the new form BEFORE disposing of the current one below
this.Dispose(); // dispose of the current form
}
With all that in place, the application will shut down automatically once the last form is closed, and the old forms should get disposed of properly.
Remember, though, that the GC manages memory for you...and it might decide that it is going to hold on to that memory to make things load faster in the future. This approach simply addresses the problem that the Dispose() call wasn't being hit since ShowDialog() was stopping execution.

Can't exit application

I was working on a software in Visual Studio, writing code in C#, while I noticed something. I can't figure out how to exit the application.
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ExitButton_Click(object sender, EventArgs e)
{
Application.Exit(); // This works, when I run the application and click on the button, it will indeed quit.
}
}
}
So as said, when I click on the button, it will indeed quit the application. However if I place Application.Exit(); somewhere else, it won't work. So if I modify Form1() like this, it won't automatically quit the application:
public Form1()
{
InitializeComponent();
Application.Exit();
}
It would be necessary to quit the application instantly if certain conditions are met, for example if some application files are missing.
I than tried to do the following:
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
closeapp();
}
public void closeapp()
{
Application.Exit();
}
private void ExitButton_Click(object sender, EventArgs e)
{
closeapp();
}
}
}
Now if I run the application, it will not exit automatically, however, if I click on the Exit button, it will quit the application.
So it looks like that if it is not called from a event that happens within the form, it will not close the application.
I have searched online (including Google and StackOverflow) with the keyword "Application.Exit();" not working. They recommended that I use "Environment.Exit();". Now in my testing application, this works, but in the real application that I am working on, when I remove all the code (of course while having a backup), it looks like the following and it still does not work.
namespace Censored
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Environment.Exit(1);
}
}
}
What can possibly be the cause of it not working in one application, but working in another one? Is something corrupted?
You can't apply Application.Exit when the application is being initialized. So, why don't you force to exit the application in the FormLoad if your conditions aren't met;
private void Form1_Load(object sender, EventArgs e)
{
Application.Exit();
}
I think the best thing to do here is not Application.Exit because as you said, you want to quit the application because there are some files missing. If there are indeed some files missing, you should really show a message to the user and then quit. Application.Exit will quit the application silently so the user does not know that some files are missing. Bad UX!
One easy way to show an error message is to throw an exception:
throw new FileNotFoundException(
"Some application files are missing! Please add them in before starting this application!");
The reason why Application.Exit does not work here is because the "Application" has not been created at that point in time. In your Main method, you should have this line:
Application.Run(new Form1());
The "Application" will be created after the above method is called. But before Run is called, what else is called? The form's constructor! It then calls InitializeComponent, where you want to exit the application. At this time Run has not been called yet!

Show "please wait" message box

I want to show a 'please wait' message box while my main form is doing a lengthy task. As for my case, the lengthy task is transmitting serial protocol. Below is my code:
public void transmitprotocol()
{
try
{
MessageBox.Show("Please wait. Uploading logo.", "Status");
// Transmitting protocol coding here. Takes around 2 minutes to finish.
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
I've tried the above method using MessageBox like the above coding, but I always have to close the MessageBox only it will start transmitting protocol.
Is there any method I can do to still show the 'please wait' MessageBox while it transmit protocol?
You will need to do the expensive operation on a background thread. For that, use either a BackgroundWorker or the new Parallelization Library (.NET 4 and so on).
Actually you need to close the dialog because it blocks the execution until you, well, close it. What you do is that you start the operation, then show the dialog and then, once the operation is done, you close the dialog.
Now, if you're using WPF I will strongly suggest you to don't use a Dialog Box and instead use a Busy Indicator, it's free, pretty easy to use and not so ugly as the Message Box.
EDIT: Now that you specify you're using WinForms, then go ahead, implement the background worked and, why not, a transparent window without chrome whose purpose is to show a Busy label. Once the background worker ends you close that window.
You have to prepare a backgroundworker and use a windows form instead of MessageBox.
Something like this as simple as copy/paste:
Form1 msgForm;
public void transmitprotocol()
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
//you can use progresschange in order change waiting message while background working
msgForm = new Form1();//set lable and your waiting text in this form
try
{
bw.RunWorkerAsync();//this will run all Transmitting protocol coding at background thread
//MessageBox.Show("Please wait. Uploading logo.", "Status");
msgForm.ShowDialog();//use controlable form instead of poor MessageBox
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// Transmitting protocol coding here. Takes around 2 minutes to finish.
//you have to write down your Transmitting codes here
...
//The following code is just for loading time simulation and you can remove it later.
System.Threading.Thread.Sleep(5*1000); //this code take 5 seconds to be passed
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//all background work has complete and we are going to close the waiting message
msgForm.Close();
}
The easiest way to do this is to open the splash with show()
Open the desired form and pass it an instance of the splash form in the constructor:
Wait myWaitDialog = new Wait(); //Wait is your splash
myWaitDialog.Show();
myWaitDialog.Refresh(); //Otherwise screen fails to refresh splash
ScheduleClassForm myForm = new ScheduleClassForm(myWaitDialog);
myForm.TopLevel = true;
myForm.ShowDialog();
Add this code to your resulting form constructor:
public ScheduleClassForm(Form WaitWindow)
{
InitializeComponent();
WaitWindow.Close();
}
For me it failed in the form_load but worked in the constructor. Make sure your work is done (e.g. db load) prior to closing the WaitWindow.

C# Windows application prevents Windows from shutting down / logging off

I have written a C# Windows Forms application, not a service (it is only used when the user is logged in and has a graphical user interface) that has a background thread running in an infinite loop.
When I try shutting down Windows (7) however, it tells me the program is preventing it from shutting down or logging off and asks me whether I want to force a shutdown.
Now, is there any possibility for my program to become aware (get a handler) of Windows trying to quit it or to log off?
So, what I need is to make the application realize when Windows tries to quit.
Thanks in advance.
EDIT: Thanks for the great advice! Is it in any way possible to use the idea with the form closing event if it has a CANCEL event handler?
public Form1()
{
InitializeComponent();
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
}
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// Or any of the other reasons suitable for what you want to accomplish
if (e.CloseReason == CloseReason.WindowsShutDown)
{
//Stop your infinite loop
}
}
You call that thread a "background thread" but does it have IsBackground = true; ?
The system will only stop a thread that does.
I think Capture console exit C# should also be usable in your scenario.
Apart from that, maybe it is sufficient to set up your thread as background thread?
Take a look at the Microsoft.Win32.SystemEvents.SessionEnding event.

C#: Proper way to close SerialPort with Winforms

I have an app where I read from the serialport, everything goes fine, until I close the app. When I click on the [X] the app simply hangs, the UI: unresponsive.
I read from the port in the DataReceived event handler, and I close the port when FormClosed happens:
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
mySerialPort.Close();
}
It's not a bug.
The only reason it would hang when you close it is because in the event handler of your SerialPort object, you're synchronizing a call with the main thread (typically by calling invoke). SerialPort's close method waits for its EventLoopRunner thread which fires DataReceived/Error/PinChanged events to terminate, but since your own code in the event is also waiting for main thread to respond, you run into a dead lock situation.
The reason the bug report was closed 'as designed' is because the 'bug' is in your own code.
Serial Port hangs while closing
This is a known issue with the SerialPort class and described in this Product Feedback article as well as several threads in these forums. You may notice the "closed by design" dismissal.
If your application is calling Invoke to process recevied data try calling BeginInvoke instead.
Instead of:
this.Invoke(d, new object[] { s, tb });
use:
this.BeginInvoke(d, new object[] { s, tb });
Simplest solution if you only want to close the port when the app closes, is to just not bother to Close() the port. The port will still get closed anyway when the app disposes of the serial port. The port will be available to be opened again by your app when it restarts, or by other apps that may wish to use the port.
this work very good :
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if (_serialPort.IsOpen)
{
e.Cancel = true; //cancel the fom closing
Thread CloseDown = new Thread(new ThreadStart(CloseSerialOnExit)); //close port in new thread to avoid hang
CloseDown.Start(); //close port in new thread to avoid hang
}
}
private void CloseSerialOnExit()
{
try
{
_serialPort.Close(); //close the serial port
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); //catch any serial port closing error messages
}
this.Invoke(new EventHandler(NowClose)); //now close back in the main thread
}
private void NowClose(object sender, EventArgs e)
{
this.Close(); //now close the form
}

Categories