How to close a console application within the specified number of hours? - c#

I was tasked to append a timer within my working console app to let it close automatically after some time without requiring a user input.
My application has functions that delete certain data in the database based on some conditions and exits everytime the user inputs 'exit'.
Now the requirement is to automatically stop the process even if the deleting of items is not yet done given that the time set to close the application is provided, say 2 hours.
Can someone help me?
Thanks.

You can create a System.Timers.Timer with an interval of TimeSpan.FromHours(2) and call Environment.Exit() in its Elapsed handler.

I don't believe that killing the program is a good idea since you are manipulating data in a database but I think would be the simplest way to do it.
using Timer = System.Threading.Timer;
class Program
{
private static readonly Timer _timer =
new Timer(o => Environment.Exit(0), null, 5000, Timeout.Infinite);
static void Main(string[] args)
{
Console.ReadLine();
}
}

1) create a timer
2) set interval and the elapsed event handler
3) enable the timer for run
when timer triggers in the method hooked to the event just exit the application

If you are deleting data from database then stopping it Abruptly could be catastrophic. So you can implement somthing like this.
Perform the time consuming operation in a BackGroundWorker
Implement a Timer as explained in other examples.
Then when the Tick/Interval Event is raised Request the BackgroundWorker to Cancel the Task.
In your Do Work code Listen for this Cancel request and stop the deletion process safely(Either the Do Deletion or Don't Perform the it At all)
Then Use Environment.Exit() to exit out of the program.
Hope it helps

I solved this problem by having an app.config file where there is a value for key="Stoptime".
I then added a condition that checks the current time against the set end time. Following is an example solution (for those having the same problem):
public static void Main(string[] args)
{
string stoptime = ConfigurationManager.AppSettings["Stoptime"];
DateTime timeEnd = Convert.ToDateTime(stoptime);
today = DateTime.Now;
Console.WriteLine(today);
for (int i = 0; i < 100000; i++)
{
id.Add(i.ToString());
}
foreach(string item in id)
{
today = DateTime.Now;
if (timeEnd.CompareTo(today) >= 0)
{
Console.CursorLeft = 0;
Console.Write(item + " " + today);
}
else
{
Console.WriteLine();
Console.WriteLine("break.");
break;
}
}
Console.ReadKey();
}

Related

How to reduce the processor consumption?

I have made a C# alarm clock and it's working fine. the problem is that when it runs it consumes 20% of the processor (on an i5 2410M processor) what should I do?
here is my code:
using System;
namespace assigment1
{
class Program
{
static void Main(string[] args)
{
DateTime uptime = new DateTime (2013,12,10,4,0,0);
Console.WriteLine("This alarm is set to go off at 4:00 am");
while (true)
{
if (DateTime.Now.Minute == uptime.Minute && DateTime.Now.Hour == uptime.Hour)
{
for (int j = 1000; j < 22767; j++)
{
Console.Beep(j, 500);
Console.Write("Wake up! it is {0}:{1} already! ", DateTime.Now.Hour, DateTime.Now.Minute);
}
}
}
}
}
}
This is because your while loop is running continuously without any break. Add a Thread.Sleep. This will add a pause in between checks and greatly increase your performance:
class Program
{
static void Main(string[] args)
{
DateTime uptime = new DateTime (2013,12,10,4,0,0);
Console.WriteLine("This alarm is set to go off at 4:00 am");
while (true)
{
if (DateTime.Now.Minute == uptime.Minute && DateTime.Now.Hour == uptime.Hour)
{
for (int j = 1000; j < 22767; j++)
{
Console.Beep(j, 500);
Console.Write("Wake up! it is {0}:{1} already! ", DateTime.Now.Hour, DateTime.Now.Minute);
}
}
Thread.Sleep(1500); // Sleep 1.5 seconds.
}
}
}
You need to calculate the time till till the alarm should beep and use the timer class. Just set the interval to the time remaining till alarm and stop the timer after that. Something like this should work
DateTime alarmTime = new DateTime(2013,12,10,4,0,0);
System.Windows.Forms.Timer alarmTimer = new System.Windows.Forms.Timer();
alarmTimer.Interval = (alarmTime - DateTime.Now).Milliseconds;
alarmTimer.Tick += alarmTimer_Tick;
alarmTimer.Start();
your event
void alarmTimer_Tick(object sender, EventArgs e)
{
alarmTimer.Stop();
Console.Write("Wake up! it is {0}:{1} already! ", DateTime.Now.Hour, DateTime.Now.Minute);
}
if you want an alarm clock why you don't use Timer Class
I don't know if you can do that, but you can change the thread priority of the executing thread via the Priority property. You may want to try the following:
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
Also, I don't think you really want to cap it. If the machine is otherwise idle, you'd like it to get busy on with the task, right? ThreadPriority helps communicate this to the scheduler.
You are putting the check within a while loop, which means it will be utilising a large proportion of your processor time.
I would suggest having a look at this article (http://www.infolet.org/2012/11/create-digital-clock-on-c-sharp-program-code.html) which describes how to do this using the Timer Class.
UPDATE:
This SO answer is pretty nice and may be more suited if you're happy to use events;
https://stackoverflow.com/a/1493235/465404
I think you should definitely be using a Timer class for your alarm and just change the tick interval accordingly. This will easily allow you to manage recurrence of the alarm as well.
So you're interval will be the difference in time between when the alarm is set and when you want it to go off.
I have used multiple of these running concurrently in a Win Forms app with very small resource utilisation.

Executing a Function at a Specific time

I have a timer running in my app which I want to stop and start according to local time.
So I need something like this:
if ( time = 08:00) {StartTimer();}
If ( time = 18:00) {StopTimer();} //This can be done from the timer event itself
Is there a way to do this without using another timer?
I can stop the timer from within the timer event itself, but how will i start it again?
You can set the timer's interval to 14 hours instead of stopping it or keep it running with short interval and checking additional condition (the time of the day) internally.
You can try this:-
1) Create a console app that does what you're looking for.
2) Use the Windows "Scheduled Tasks" functionality to have that console app executed at the time you need it to run
or
You can also look at this example:-
using System;
using System.Threading;
public class TimerExample {
// The method that is executed when the timer expires. Displays
// a message to the console.
private static void TimerHandler(object state) {
Console.WriteLine("{0} : {1}",
DateTime.Now.ToString("HH:mm:ss.ffff"), state);
}
public static void Main() {
// Create a new TimerCallback delegate instance that
// references the static TimerHandler method. TimerHandler
// will be called when the timer expires.
TimerCallback handler = new TimerCallback(TimerHandler);
// Create the state object that is passed to the TimerHandler
// method when it is triggered. In this case a message to display.
string state = "Timer expired.";
Console.WriteLine("{0} : Creating Timer.",
DateTime.Now.ToString("HH:mm:ss.ffff"));
// Create a Timer that fires first after 2 seconds and then every
// second.
using (Timer timer = new Timer(handler, state, 2000, 1000)) {
int period;
// Read the new timer interval from the console until the
// user enters 0 (zero). Invalid values use a default value
// of 0, which will stop the example.
do {
try {
period = Int32.Parse(Console.ReadLine());
} catch {
period = 0;
}
// Change the timer to fire using the new interval starting
// immediately.
if (period > 0) timer.Change(0, period);
} while (period > 0);
}
// Wait to continue.
Console.WriteLine("Main method complete. Press Enter.");
Console.ReadLine();
}
}
You could create a thread that ticks every second.
There you can check if you want to start or stop your timer.
Read the folowing: Threads.
In your thread add something like:
if (CurrentTime == "08:00")
StartTimer();
else if if (CurrentTime == "18:00")
StopTimer();
Thread.Sleep(1000); // Makes the Thread Sleep 1 Second
Since you need at least one timer running always (to detect when it's 8 in the morning) then you could simply have just a single timer that runs all day.
Whenever the timer ticks, check the time. If it isn't between 0800 and 1800 just return without doing anything and wait for the next tick.
You could try increasing the timer interval to a value that gets you to e.g. 17:55 and then decrease it again, but there will not be any measurable performance difference so IMHO this is work for no benefit.

C# BackgroundWorker

I have a button that on click event I get some information from the network.
When I get information I parse it and add items to ListBox. All is fine, but when I do a fast double-click on button, it seems that two background workers are running and after finishing all work, items in the list are dublicated.
I want to do so that if you click button and the proccess of getting information is in work, this thread is stopping and only after first work is completed the second one is beginning.
Yes, I know about AutoResetEvent, but when I used it it helped me only one time and never more. I can't implement this situation and hope that you will help me!
Now I even try to make easier but no success :( : I added a flag field(RefreshDialogs)(default false), when the user clicks on button, if flag is true(it means that work is doing), nothing is doing, but when flag field is set to false, all is fine and we start a new proccess.
When Backgroundwork completes, I change field flag to false(it means that user can run a new proccess).
private void Message_Refresh_Click(object sender, EventArgs e)
{
if (!RefreshDialogs)
{
RefreshDialogs = true;
if (threadBackgroundDialogs.WorkerSupportsCancellation)
{
threadBackgroundDialogs.CancelAsync();
}
if (!threadBackgroundDialogs.IsBusy)
{
downloadedDialogs = 0;
threadBackgroundDialogs = new BackgroundWorker();
threadBackgroundDialogs.WorkerSupportsCancellation = true;
threadBackgroundDialogs.DoWork += LoadDialogs;
threadBackgroundDialogs.RunWorkerCompleted += ProcessCompleted;
threadBackgroundDialogs.RunWorkerAsync();
}
}
}
void ProcessCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RefreshDialogs = false;
}
So you want to keep the second process running while the first works, but they shouldn't disturb each other? And after the first one finishes the second one continues?
Crude way: While loop:
if (!RefreshDialogs)
{
RefreshDialogs = true;
this becomes:
while(RefreshDialogs)
{
}
RefreshDialogs = true;
After you set it false the second process wwill jump out of the while. (Note this is extremly inefficent since both processes will be running all the time, i'm pretty sure the second one will block the first one, but with multitasking now it shouldn't, if it block use a Dispatcher.Thread)
Elegant way: Use A Semaphore
http://msdn.microsoft.com/de-de/library/system.threading.semaphore%28v=vs.80%29.aspx
If you find it impossible to have both processes running at the same time, or want another way:
Add an Array/List/int and when the second process notices there is the first process running, like with your bool, increase your Added variable, and at the end of the process, restart the new process and decrese the variable:
int number;
if (!RefreshDialogs)
{
RefreshDialogs = true;
your code;
if(number > 0)
{
number--;
restart process
}
}
else
{
number++;
}
I have to admit, i like my last proposal the most, since its highly efficent.
Make your thread blocking. That is easy;
lock(someSharedGlobalObject)
{
Do Work, Exit early if cancelled
}
This way other threads will wait until the first thread releases the lock. They will never execute simultaneously and silently wait until they can continue.
As for other options; why not disable the button when clicked and re-enable it when the backgroundworker completes. Only problem is this does not allow for cancelling the current thread. The user has to wait for it to finish. It does make any concurrency go away very easily.
How about this approach?
Create a request queue or counter which will be incremented on every button click. Every time that count is > 0. Start the background worker. When the information comes, decrement the count and check for 0. If its still > 0 restart the worker. In that your request handler becomes sequential.
In this approach you may face the problem of continuous reference of the count by two threads, for that you may use a lock unlock condition.
I hav followed this approach for my app and it works well, hope it does the same for you.
I'm not an Windows Phone expert, but as I see it has support for TPL, so following code would read nicely:
private object syncRoot =new object();
private Task latestTask;
public void EnqueueAction(System.Action action)
{
lock (syncRoot)
{
if (latestTask == null)
latestTask = Task.Factory.StartNew(action);
else
latestTask = latestTask.ContinueWith(tsk => action());
}
}
Use can use semaphores
class TheClass
{
static SemaphoreSlim _sem = new SemaphoreSlim (3);
static void Main()
{
for (int i = 1; i <= 5; i++)
new Thread (Enter).Start (i);
}
static void Enter (object name)
{
Console.WriteLine (name + " wants to enter");
_sem.Wait();
Console.WriteLine (name + " has entered!");
Thread.Sleep (1000 * (int) name );
Console.WriteLine (name + " is leaving");
_sem.Release(); }
}
}
I found the solution and thanks to #Giedrius. Flag RefreshingDialogs is set to true only when proccess is at the end, when I added items to Listbox. The reason why I'am using this flag is that state of process changes to complete when the asynchronous operation of getting content from network(HttpWebRequest, method BeginGetRequestStream) begins, but after network operaion is complete I need to make UI operations and not only them(parse content and add it to Listbox)My solution is:
private object syncRoot = new object();
private Task latestTask;
public void EnqueueAction(System.Action action)
{
lock (syncRoot)
{
if (latestTask == null)
{
downloadedDialogs = 0;
latestTask = Task.Factory.StartNew(action);
}
else if(latestTask.IsCompleted && !RefreshingDialogs)
{
RefreshingDialogs = true;
downloadedDialogs = 0;
latestTask = Task.Factory.StartNew(action);
}
}
}
private void Message_Refresh_Click(object sender, EventArgs e)
{
Action ac = new Action(LoadDialogs2);
EnqueueAction(ac);
}

How can i make that my application will close and start and close automatic over and over again?

I want to check if a problem that sometimes show up and sometimes not still happen.
So instead closing manual the application and start again all the time is there anything that can make it automatic untill the problem will show up ? Or something that will simulate Form Closing.
You can try this
Timer timer;
public void StartTimer()
{
timer = new Timer();
timer.Interval = 5000; // 5 seconds
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
Process[] p = Process.GetProcessesByName("TheApp");
if (p.Length == 0) {
// Restart the app if it is not running any more
Process.Start(#"C:\Programs\Application\TheApp.exe");
} else {
p[0].CloseMainWindow();
}
}
Use a Timer to call a method at certain intervalls. When the Timer ticks, look if a process with the given name exists. If it exists close its main window (do not just kill it). If it does not exist, start it.
How about writing a simple bat program to kill your app and start it again? Look for "Taskkill" command for console. If I have to kill notepad, I will use "taskkill /f /im notepad.exe"
You can make it to require a keypress to perform iterations and induce delay before killing of app.
Just for fun, if you really wanted to do something, try a simple C# app that does the following:
for (int i = 0; i < 100; ++i)
{
Process proc = Process.Start("ExecutablePath");
Thread.Sleep(1000);
proc.Kill();
}
If You want to simulate user behaviour You should try AutoIT or AHK or SIKULI

How to add a timer to an app!

I have an app that I would like to update on an interval. I am looking for maybe some type of if statement or try - catch statement. I already have a foreach statement in the same class, but i dont think I can put in there? I would also like to set it up so that the user can change the refresh rate. Any help is appreciated. Thanks
Here is the method that I would like to put the timer in...
private void _UpdatePortStatus(string[] files)
{
foreach (string file in files)
{
PortStatus ps = new PortStatus();
ps.ReadXml(new StreamReader(file));
if (!_dicPortStatus.ContainsKey(ps.General[0].Group))
{
_dicPortStatus.Add(ps.General[0].Group, ps);
}
PortStatus psOrig = _dicPortStatus[ps.General[0].Group];
foreach (PortStatus.PortstatusRow psr in ps.Portstatus.Rows)
{
DataRow[] drs = psOrig.Portstatus.Select("PortNumber = '" + psr.PortNumber + "'");
if (drs.Length == 1)
{
DateTime curDt = DateTime.Parse(drs[0]["LastUpdateDateTimeUTC"].ToString());
DateTime newDt = psr.LastUpdateDateTimeUTC;
if (newDt > curDt)
{
drs[0]["LastUpdateDateTimeUTC"] = newDt;
}
}
else if (drs.Length == 0)
{
psOrig.Portstatus.ImportRow(psr);
}
else
{
throw new Exception("More than one of the same portnumber on PortStatus file: " + file);
}
}
}
}
Look at the System.Timer class. You basically set an interval (eg. 10000 milliseconds) and it will raise an event every time that interval time passes.
To allow the use to change the refresh rate, write a method that receives input from the user and use that to update the TimerInterval. Note that the TimerInterval is in miliseconds, so you may need to convert to that from whatever the user input.
So, from the example, the event will be raised every 10 seconds:
System.Timers.Timer aTimer = new System.Timers.Timer(10000); //10 seconds
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true; // Starts the Timer
// Specify what you want to happen when the Elapsed event is raised
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//Perform update
_UpdatePortStatus(files);
}
UPDATE: In response to your posted code, it appears you simply want to call _UpdatePortStatus to update the port status at regular intervals (see the updated example above).
One important point you need to bear in mind though is that the Timer will run on a separate thread, and as such could raise the event again before it has finished running from the last time if it takes more than the interval time to run.
Use System.Timers.Timer, System.Threading.Timer or System.Windows.Forms.Timer ... depending on what exactly it is that you "would like to update on an interval."
See the following articles:
http://www.intellitechture.com/System-Windows-Forms-Timer-vs-System-Threading-Timer-vs-System-Timers-Timer/
http://www.yoda.arachsys.com/csharp/threads/timers.shtml
Your question is somewhat vague as there an many different methods of achieving what you want to do. However in the simplest terms you need to create a System.Threading.Timer that ticks on whatever frequency you define, for example:
private System.Threading.Timer myTimer;
private void StartTimer()
{
myTimer = new System.Threading.Timer(TimerTick, null, 0, 5000);
}
private void TimerTick(object state)
{
Console.WriteLine("Tick");
}
In this example the timer will 'tick' every 5 seconds and perform whatever functionality you code into the TimerTick method. If the user wants to change the frequency then you would destroy the current timer and initialise with the new frequency.
All this said, I must stress that this is the simplest of implementation and may not suit your needs.

Categories