Avatar of Jeff Heilman
Jeff Heilman
Flag for United States of America asked on

C# WPF how to ensure application keeps running 24/7

I have a simple C# WPF application that shows production data in a datagrid that is bound to a tableadapter in a dataset linked to a SQL database table.  The only function is to display this information 24/7, it is not used to add or edit data.  My question is pretty general, what is the best way to ensure this application keeps running?  Every now and then it will stop working until I reopen the application.  Perhaps the way to handle it is to just relaunch the app any time it throws an exception?  The only message I get right now when it crashes is "Production Counter has stopped working.".

I'm new to C# and I am interested in your opinions/sample code/ideas, I'm looking to learn.  Thank you!

namespace ProductionCounter
{

    public partial class MainWindow : Window
    {
        public DispatcherTimer _timer = null;
        public MainWindow()
        {
            InitializeComponent();
            Initializeload();

            // Start the timer to refresh every 10000ms thereafter (change as required)
            _timer = new DispatcherTimer();
            _timer.Tick += Each_Tick;
            _timer.Interval = new TimeSpan(0, 0, 0, 0, 10000);
            _timer.Start();

            var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            lblVersion.Content = string.Format("Version {0}", version);

            string machineName = Environment.MachineName;            
            lblMachineName.Content = machineName;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Initializeload();
        }

        private void Each_Tick(object o, EventArgs sender)
        {
             Initializeload();
        }

        private void Initializeload()
        {
            
                string machineName = System.Environment.MachineName;

                string connString = ConfigurationManager.ConnectionStrings["ProductionCounter.Properties.Settings.MyConnectionString"].ConnectionString;

                SqlDataAdapter da = new SqlDataAdapter("Select Department From tblQMSTerminalID WHERE TerminalID = @mach", connString);
                da.SelectCommand.Parameters.AddWithValue("@mach", machineName);
                DataSet ds = new DataSet();
                da.Fill(ds);
                string pl = ds.Tables[0].Rows[0]["Department"].ToString();
                lblProdLine.Content = pl;

                SqlDataAdapter sa = new SqlDataAdapter("SELECT MAX(UPWHID) AS MaxOfUPWHID, Shift, Dept, MAX(ShiftDate) AS MaxShiftDate, " +
                    "MIN(StartTime) AS MinStartTime FROM tblQMSUPWH WHERE Dept = @pline GROUP BY Dept, Shift", connString);
                sa.SelectCommand.Parameters.AddWithValue("@pline", pl);
                DataSet sd = new DataSet();
                sa.Fill(sd);
                string shift = sd.Tables[0].Rows[0][1].ToString();
                string sdate = sd.Tables[0].Rows[0][3].ToString();
                lblShift.Content = shift;
                lblDate.Content = Convert.ToDateTime(sdate);

                SqlDataAdapter pa = new SqlDataAdapter("SELECT Dept, Shift, ShiftDate, FLOOR(SUM(RunningGoal)) AS Target, SUM(UnitsProd) AS Produced " +
                    "FROM vw_PRODCOUNTER_HourlyProduction WHERE Dept = @pline AND Shift = @shift AND ShiftDate = @sdate GROUP BY Dept, Shift, ShiftDate", connString);
                pa.SelectCommand.Parameters.AddWithValue("@pline", pl);
                pa.SelectCommand.Parameters.AddWithValue("@shift", shift);
                pa.SelectCommand.Parameters.AddWithValue("@sdate", sdate);
                DataSet pd = new DataSet();
                pa.Fill(pd);
                string prod = pd.Tables[0].Rows[0][4].ToString();
                string target = pd.Tables[0].Rows[0][3].ToString();
                txtProduced.Text = prod;
                txtTarget.Text = target;
          
        }
    }
}

Open in new window

DatabasesC#SQL* WPF

Avatar of undefined
Last Comment
Pavel Celba

8/22/2022 - Mon
Pavel Celba

You may create recurrent job in Windows Task Scheduler. It allows to start the application after the login and restart each time it exits or crashes.

Application exceptions may be solved later... You just have to save them to a log file for analysis. Google for NLOG.
Chinmay Patel

Hi Jeff,

If I wanted to make sure that my app is kept running 24x7 and it is a mission critical app, I would rather keep it under a check using a Windows Service(running with Network Service account to save you the trouble of managing a dedicated Service Account - though, depending upon your requirements, you might want to cross check with your IT Admin/Security folks). While it is a bit complex to implement (If you are new to C#), in long term, you will rip the benefits.

I personally have never used this and I think I will never use it (I dunno why, I think I would rather use my own framework) but many swear by a service hosting framework called TopShelf http://topshelf-project.com/, you might want to check it out.

PS: If you are new to C# :D... this is a great learning opportunity as well.

Regards,
Chinmay.
Pavel Celba

Windows Service is a bad choice in this case because it cannot have UI so you have to maintain two applications in such case - 1. The Windows Service and 2. The UI running 24/7 as a front-end for the Windows service which in turn is easier to implement as one interactive application. So we are back in your WPF application and Windows Task Scheduler...

Of course, the service can produce web content and you may use web browser as a front-end to display it or you may code it as ASP.NET application but that's not task which could have simple and straight forward implementation at this phase.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Jeff Heilman

ASKER
pcelba, I looked at the Task Scheduler and didn't see an option for Recurrent Job.  Can you elaborate just a bit on this?  Thanks.
Jeff Heilman

ASKER
Thank you for the link Chinmay, I'll definitely check it out.
Éric Moreau

You could restart the application by using code like this:
System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
Application.Current.Shutdown();

Open in new window

⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Jeff Heilman

ASKER
I just stumbled across that a little while ago Eric.  Could I put that in a catch?
ASKER CERTIFIED SOLUTION
Éric Moreau

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Pavel Celba

Recurrent Job in Task Scheduler - try various Triggers settings one of them states "Repeat every X hours/minutes"
Settings allow to set what to do when the task fails.

So you may start the task every 5 minutes but do nothing when it is running already. This will restart the task automatically when it exits after exception. (Not all exceptions is possible to trap in TRY - CATCH)
Pavel Celba

Of course, the above recurrence is achievable by simple batch program with one loop which will start the EXE again and again when it exits.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes