How to properly exit a multi-threaded program - c#

I made a program based on Aforge (it's a video library). This library creates its own refresh events for the next video frame from camera. So far so good, earlier people have helped me with multi threading so these Aforge threads could report back to the main program thread, again so far so good, it works great.
The code can be seen here: how to do multithreading when using outside referenced code.
But now I regularly notice a new program error. The problem starts when I want to exit the program. At the moment the Aforge thread might still be active. And it wants to write back to main form that is closed.
Somehow I need to stop the other thread before I close the program. There is an option in Aforge to do something like camera stop, but it's not enough. But then still my code wants to write on the main form that's already closing.
Is there a way to stop all threads, or some safe way to close from the originating thread? I even placed the back reporting to the main program in a try catch construction but it didn't work well, the only way of stopping it in these situations is to press the stop execution button within Visual Studio itself.

If I understand your problem correctly, you may have an Invoke call about to happen on your form just as you've closed the form. I've had this happen as well.
What I've done is to set a "shutdown" variable when I start to close the form, and then use AppDomain.CurrentDomain.UnhandledException to watch for InvalidOperationException (or whatever you're getting), and ignore if shutdown is set.

Related

Crash 15 minutes after showing a Window

I have an application (based on the XNA project template) that in the beginning shows a window so that the user can change some settings. After that the Window is closed and the program continues in another window managed by XNA. Almost exactly 15 minutes after that the program crashes in a thread named Win32 that is not the main thread (but was never spawned by me) with an access violation.
Using the standard debugger there isn't even a stack trace. Using the native debugger it only shows that the access violation occurred in Kernel32!BaseThreadInitThunk which is an undocumented method. At the same time the main thread still seems to be happily executing the main game loop.
Keep in mind that the application is a pure C# application so this is really baffling me.
After some testing I figured out that this even happens if I show an empty window:
Window window = new Window();
window.ShowDialog();
So removing the above two lines in my code makes the program completely stable. Adding them back guarantees the access violation after 15 minutes (+- 30 seconds).
I've checked that the main thread, which spawns the window, is an STA thread. I've also tried to manually start the dispatcher, but that doesn't seem to help (the dispather seems to be already running) and I even tried to shutdown the dispatcher after I showed the window, also to no effect.
I've also tried to show the window using techniques for showing windows in multiple threads described in this answer. But that also had no effect. I even tried launching a completely separate thread to show the window (using the same technique). This also had no effect.
How can these two lines of code make my program crash 15 minutes later? What kind of clean-up of an empty, standard, window could be necessary?
Sounds like a memory related issue from not disposing objects properly...

Maintaining a countdown clock upon program termination

I am learning to program in C# for .Net using VS2015 Community Ed.
Its my first question so if I am not in the correct format I apologize.
At present I am trying to click a button and have the program begin a countdown. This countdown item should be named (ie..Timer1) and its name appear in a ComboBox. That part is the easy part. The part where I am having an issue is figuring out how to have the timer continue if the program is terminated.
Is there a way to keep the countdown running after program termination until specifically terminated by the user? If so, What should I be searching for in order to learn this?
You could hide your form but the timer still continue, but there is no space for the timer to run if you close the application. It has to live in an application. I think what you're probably looking for is it living longer than your form, that is possible, just move the timer's scope up higher than the form, you'll have to play with the Program class, maybe make the form modeless instead of modal, or maybe not. You'll have to try a few ways. But the timer will have to run in your application, everything in your application dies when the application does.
The only way to have your timer continue to run after your process exits is to launch a separate process in which the timer will run. Of course, the original process will no longer have access to the timer, so you'll need to use some form of interprocess communication to allow the timer process to inform the original process of the timer state.

GUI does not redraw while stepping in Debug Mode

In any .NET 2.0 Winforms application, if you run the code in Debug Mode, and you either hit a breakpoint or otherwise Step Into the code line by line, and you want to see the GUI of the application being debugged, then .NET does not draw the application screen.
For example, I have an application which writes some messages to a TextBox on a Form. When I debug the code step by step, or when a breakpoint is hit, I want to see what all messages are logged in the TextBox, but if I press Alt-Tab to switch from VS2005 window to the WinForms application window, all I see is white color. The form is not redrawn, until you press F5 in the debug mode in VS2005.
What is the reason for this, and is there a way to overcome this, without introducing any threads in the code?
What is the reason for this
While you're debugging, you're effectively blocking the UI thread - you're manually stepping through its execution flow. The UI thread can't draw the UI while you're stopping it from executing.
and is there a way to overcome this
You could try calling Application.DoEvents() manually, but I'd generally recommend against it.
It would be better to just wait until you got to the end of the method and let the UI redraw itself normally. If your method is very long (in terms of time) then bear in mind that when not debugging, the UI still wouldn't be able to update itself while that method is executing. This may cause you to change your design (it's hard to tell just from the information we've got at the moment).
The reason for this is because you can only have one UI thread, and when you enter your method that updates that code that code begins blocking the UI thread. It will not update until your method exits.
Here is a good SO on message pumps, which are what drive the UI updates
You should be able to use Add Watch/Quick Watch to look at any values at the time of debugging. This sounds like what you are really looking for, anyway.
Like everyone else has said in answers and comments, the UI thread is blocked so it cannot be redrawn.
However, if all you want to do is see the GUI, and not interact with it, and you are running Windows 7/8 (which sounds unlikely since you're using VS2005) and haven't disabled aero peek, you can mouse over your application in the task bar and Windows will show the preview thumbnail. When you mouse over the thumbnail, you can "peek" at the application even when the breakpoint is blocking the UI thread.

Do I have to close running BackgroundWorkers when user closes form?

From here Does closing the application stops all active BackgroundWorkers? it seems not.
But from here How to stop BackgroundWorker on Form's Closing event? it seems yes.
So which is it?
(EDIT: I realize that the BackgroundWorkers might exit with an exception. But what's the problem with that? Isn't the point here to not leave running threads which take up resources?)
Closing a Form does not stop all background workers started by that form.
When the entire application ends it will stop all background threads.
Closing the main form (unless you have modified the Main method to do something else) will end the entire application.
Each question you referenced is correct for what it says. If you close the main form, then the entire application will end and the background worker will be closed on its own. If the form that is closing isn't the main form, but some other form, and you want the background worker that it starts to be stopped, then you will need to do so yourself.
It's also worth noting that the second link that you have provided asks for something a bit more complex. It's clear in that post that closing the form (if it's the main form) will stop execution of the background thread. What the OP is trying to do there is to tell the background thread, "hey, it's time to finish up, we're done here" and then have the form wait until that background thread can finish cleaning things up nicely, rather than just exiting and forcibly aborting the thread while it's in the middle of doing something.
Both of those links that you provide have the correct answer- BackgroundWorkers will be closed when the program is closed. Unmanaged resources are the ones you have to worry about explicitly closing.

C#: Parallel forms, multithreading and "applications in application"

First, what I need is - n WebBrowser-s, each in its own window doing its own job. The user should be able to see them all, or just one of them (or none), and to execute commands on each one. There is a main form, without a browser, this one contains control panel for my application.
The key feautre is, each browser logs on to secured web page and it needs to stay logged in as long as possible. Well, I've done it, but I'm afraid something is wrong with my approach.
The question is:
Is code below valid, or rather a nasty hack which can cause problems:
internal class SessionList : List<Session> {
public SessionList(Server main) {
MyRecords.ForEach(record => {
var st = new System.Threading.Thread((data) => {
var s = new Session(main, data as MyRecord);
this.Add(s);
Application.Run(s);
Application.ExitThread();
});
st.SetApartmentState(System.Threading.ApartmentState.STA);
st.Start(record);
});
}
// some other uninteresting methods here...
}
What's going on here? Session inherits from Form, so it creates a form, puts WebBrowser into it, and has methods to operate on websites. WebBrowser requires to be run in STA thread, so we provide one for each browser. The most interesting part of it is Application.Run(s). It makes the newly created forms alive and interactive. The next Application.ExitThread() is called after browser window is closed and its controls disposed. Main application stays alive to perform the rest of the cleanup job.
When user select "Exit" or "Shutdown" option - first the browser threads are ended, so Application.ExitThread() is called. It all works, but everywhere I can read about "main GUI thread" - and here - I've created many GUI threads. I handle communication between main form and my new forms (sessions) with thread-safe methods using Invoke(). It all works, so is it right or is it wrong?
Is everything right with using Application.Run() more than once in one application? :) An ugly hack or a normal practice? This code dies if I start a WebBrowser from the session form thread. It beats me why. It works however if I start WebBrowser (by changing its Url property) from any other thread. I'd like to know more what is really happening in such application. But most of all - I'd like to know if my idea of "applications in application" is OK.
I'm not sure what exactly does Application.Run() do. Without it forms created in new threads were dead unresponsive. How is it possible I can call Application.Run() many times? It seems to do exactly what it should, but it seems a little undocumented feature to me. I'm almost sure, that the crashes are caused by WebBrowser component itself (since it's not completely "managed" and "native"). But maybe it's something else.
Is everything right with using Application.Run() more than once in one application? :) An ugly hack or a normal practice?
Some of both ;) This is perfectly acceptable, in that it will function as you are expecting, but it's not exactly a "normal practice."
I'm not sure what exactly does Application.Run() do.
Application.Run basically does a couple of things. First, it installs the property SynchronizationContext into the thread for Windows Forms to run properly. It then starts the windows message processing in that thread, which processes all messages from Windows going into the thread. This is what allows forms to work properly.
There's nothing particularly wrong with doing this, but it isn't a standard practice. Given your design goals, I do question whether this would be better served by just launching a separate process instead of trying to run each operation within a separate thread.

Categories

Resources