Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect when an Application stops Responding, Kill it and Restart it

Tags:

c#

windows

I am developing a high performance App that is causing the main process to seemingly stop responding and crash - from time to time - due to overload (I get the Close Application Dialog so the App never exits per se, just freezes, which is annoying)

I welcome any clean way to pro grammatically detect when the App is frozen, so I can use a BAT (or else) to automatically Kill the process and Restart.

Of course, this is a temporary fix while auditing the App, but it comes very handy in the meanwhile.

TieBreaker : BTW, Is there a way to override windows' Exception Screen and just quit the App ??? This is mostly annoying feature most of the time.

EDIT :
FOR GOD'S SAKE : the app IS freaking freezing, THOUGH every single task run in BG Workers and threads !!! And I specified that in comments. Come'on, I am not that dumb. Just that your app runs BG workers does not imply it never freezes ! And As I said, please JUST answer my question, I am not looking for lessons on how to design my App, that I am already working on and I know what has to be done. As specified MANY times, I just need a fix on the server in the meantime. Thank you.

like image 371
Mehdi LAMRANI Avatar asked Jan 03 '12 22:01

Mehdi LAMRANI


3 Answers

I'll say it if noone else will :) Make a separate forms app that does-

Process[] prs = Process.GetProcesses();

foreach (Process pr in prs)
{
    if (!pr.Responding) 
    {
        try
        {
            pr.Kill();
        }
        catch { }
    }
}

//then to restart-
var process = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = @"C:\yourapp.exe"
    }
};
process.Start();

Obviously oversimplified.

like image 117
Alex Avatar answered Sep 29 '22 04:09

Alex


We handle this in a service by having the main service exe be little more than a shell that launches the child threads.

The child threads are then responsible for reporting back to the parent thread whenever they can to record the last date/time they were "seen".

On a regular interval, the service app checks the list of child processes and, if one hasn't been seen for a predetermined period of time (i.e. 2 minutes), but did not report that it had closed down, the parent process will first try to join the thread and shut it down gracefully (usually fails) and then, if that didn't work, aborts the thread.

We have used this approach successfully for many years, starting when an OCR service that we were running would hang constantly due to bugs in the OCR software.

like image 37
competent_tech Avatar answered Sep 29 '22 04:09

competent_tech


Move all CPU instensive tasks off of the GUI and invoke back to the gui to report any statuses.

The main app should never freeze. I wrote an app that generated over 500 threads (all at once) and managed them as they asynchronously (.net 2) processed multiple database calls. I believe you need to systematically move all processes to a thread safe situation and remove any direct GUI calls.

ADDENDUM How did I run 500+ threads:

  1. Usage of smart locks done from the beginning on all shared data locations. See my blog articles

    Smart Resource Locking in C# .Net for Thread Safe Code
    C# MultiThreading Using ThreadPool, Anonymous Delegates and Locks

  2. Interface created which specified an action operation with data, error status as a properties.
  3. Threading base class created (for classes in #4 and #5) which created, started and cleaned up thread opertions. No business logic, just a method of handling threading in one location.
  4. Class created based on interface in #2 and also derived from step #3. Class via the interface was required to get data and place data (thread safe via localized lock) and report its status. Class also designed to give up thread cycle if no work done to be done via thread.Sleep(0) instead of busy waiting.
  5. Manager class created (which ran on its own thread and derived from #3).It launched 1-N #4 classes to do work. Each of those instances was placed into a working list.
  6. Manager class simply browsed the working list for instances which reported their work was done if it was done it moved the instance to the done work. Manager class also kept records of the status (thread safe via locks) to exposed properties (as well as any reported errors by the children instances). Manager gave up thread cycle after each run and slept for 250 milleseconds before starting again.
  7. GUI thread had working timers which dealt with getting specific status from the manager. They would extract the data from the manager's properties and invoke back the GUI to target a control (gridview) which reported all statuses and errors.

By doing that, I was able to achieve individual threads doing specific work and if a process ran into a problem it reported it, or it reported success or failure. Those messages bubbled up to the manager which bubbled up to the timers which bubbled up to the GUI. The gui handled no business logic except to start the mananager and timers.


I get that this doesn't help your situation right now and I feel your pain. But until you are able to seperate out the business logic from the GUI and handle error situations in the threads (background workers) and bubble them up to the GUI, you will still have this frustration with the current code.

If something is locking that is a sign that business logic is too tightly coupled with GUI operation and that has to be divorced before you will get the performance you want from the GUI.

HTH

like image 23
ΩmegaMan Avatar answered Sep 29 '22 04:09

ΩmegaMan