I want to produce some text in a console window for a certain amount of time before clearing it and showing more text. I thought the following code would do that, but instead, after the timer expires, the console is cleared but no other text appears.
Is this the correct way to halt program execution until a timer expires?
static void Main (string [] args)
{
const int PEEK_TIME = 5;
const int SECOND = 1000;
Timer peekTimer = new Timer (SECOND * PEEK_TIME);
peekTimer.Elapsed += onTimerTick;
peekTimer.AutoReset = false;
peekTimer.Start ();
Console.WriteLine ("Timer started...");
while (peekTimer.Enabled) { }
Console.WriteLine ("Timer done.");
Console.ReadLine ();
}
static void onTimerTick (Object source, System.Timers.ElapsedEventArgs e)
{
Console.Clear ();
}
Here is codesample using the Thread.Sleep function.
using System;
using System.Threading;
namespace ConsoleApplication
{
public class Program
{
public static void Main()
{
Console.WriteLine("Timer Start!");
Thread.Sleep(5000);
Console.Clear();
Console.WriteLine("End");
Console.ReadKey();
}
}
}
You don't need timer for this:
static void Main (string [] args)
{
const int PEEK_TIME = 5;
const int SECOND = 1000;
var task = Task.Run(()=>
{
Console.WriteLine ("Work started...");
Thread.Sleep(PEEK_TIME*SECOND);
Console.Clear();
});
task.Wait();
Console.WriteLine ("Work done.");
Console.ReadLine ();
}
In your onTimerTick event, you need to stop the timer (or set peekTimer.Enabled == false) if you want the while loop to exit:
static void onTimerTick (Object source, System.Timers.ElapsedEventArgs e)
{
Console.Clear ();
peekTimer.Stop();
}
In order to do this, you'll have to declare the timer at a wider scope so you can access it from your Main method and from the Tick event handler:
namespace ConsoleApplication
{
timer peekTimer;
public class Program
{
In answer to your larger question, this is not the best way to do it. If you're just going to sit and do nothing for a specific amount of time, you might as well just put the thread to sleep rather than spinning around the whole time:
Console.WriteLine("Waiting 5 seconds...");
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.WriteLine("...Time's up!!");
In my game I use this approach:
public static Timer peekTimer = new Timer (SECOND * PEEK_TIME);
static void Main (string [] args)
{
const int PEEK_TIME = 5;
const int SECOND = 1000;
Console.WriteLine ("Timer started...");
peekTimer.Interval = new TimeSpan(0, 0, 0, 0, SECOND * PEEK_TIME);
peekTimer.Tick += new EventHandler(onTimerTick);
peekTimer.Start();
}
static void onTimerTick (Object source, System.Timers.ElapsedEventArgs e)
{
peekTimer.Stop();
Console.Clear ();
Console.WriteLine ("Timer done.");
Console.ReadLine ();
}
Related
How can i pause a method execution or the current iteration until the user press next button for example?
I want an efficient way because i can't divide the method into other methods and I don't want to use Thread.Sleep() because it freezes the GUI.
public void Calc(int x)
{
while(x < 4)
{
//My Work
textbox1.Text += "Press next to continue";
//Need to pause the iteration until taking a signal from a button
}
}
void button1(...)
{
Calc(1);
}
Use SemaphoreSlim
You can run both work and button code on UI thread, thanks to async/await scheduling. And you can reuse same semaphore instance to make multiple signals.
//not signaled semaphore with maximum of 1 signal
SemaphoreSlim _workSignal = new SemaphoreSlim(0,1);
Your work code:
async void DoWork()
{
//Do Something
//this tries to decrease signal count and if signal count is 0,
//waits until it will have some signals, then "takes"
//one signal to go through.
//After this line the semaphore will be in non-signaled state
await _workSignal.WaitAsync();
//Do more
}
Your button handler
void Button_Click(...)
{
_signal.Release();//increases signal count, allowing your work code to go through
}
I think a simple ManualResetEvent along with async method may help you:
public partial class Form1 : Form
{
private ManualResetEvent _calcEvent;
private delegate void ChangeTextMethod(string text);
private ChangeTextMethod _changeTextHandler;
public Form1()
{
InitializeComponent();
_calcEvent = new ManualResetEvent(false);
_changeTextHandler = delegate (string text) {
textbox1.Text += text;
};
}
private void button1_Click(object sender, EventArgs e)
{
Calc(1);
}
public async Task Calc(int x)
{
await Task.Run(() => {
while (x < 4)
{
//My Work
textbox1.Invoke(_changeTextHandler, "Press next to continue");
//Need to pause the iteration until taking a signal from a button
_calcEvent.WaitOne();
x = 4;
}
textbox1.Invoke(_changeTextHandler, "... continued");
});
}
private void button2_Click(object sender, EventArgs e)
{
_calcEvent.Set();
}
}
basically I'm trying to implement the timer in class for my would-be very first game in C#; I want to use timers that will constantly update the player and provide certain periodic feedback, but I can't seem to get the 'timer' class to work correctly. If I use it in a loop (as shown below), it will wait 2 seconds, and then keep writing "You're Alive!" to the console with 0 delay in-between; and if I do not use the loop, the application just ends instantly.
using System;
using System.Timers;
public class MyClass
{
public static void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("You're alive!");
}
public static void Main(String[] args)
{
while (true)
{
Timer MyTimer = new Timer();
MyTimer.Interval = 2000;
MyTimer.Enabled = true;
MyTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
MyTimer.Start();
}
}
Just add below line after MyTimer.Start();
Console.ReadLine();
static void Main(String[] args)
{
Timer MyTimer = new Timer();
MyTimer.Interval = 2000;
MyTimer.Enabled = true;
MyTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
MyTimer.Start();
Console.ReadLine();
}
private static void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("You're alive!");
}
I'm using a System.Timers.Timer in my application. Every second I run a function which does some job. The thing is, this function can block for some little time (it reads then processes a large file from disk). I want to start that function only if its previous "execution instance" has completed. I thought I could achieve this with a Mutex:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static Mutex TimerMut = new Mutex(false);
public static void Main()
{
Thread TT = new Thread(new ThreadStart(delegate()
{
System.Timers.Timer oTimer = new System.Timers.Timer();
oTimer.Elapsed += new ElapsedEventHandler(Handler);
oTimer.Interval = 1000;
oTimer.Enabled = true;
}));
TT.Start();
Console.Read();
}
private static void Handler(object oSource,
ElapsedEventArgs oElapsedEventArgs)
{
TimerMut.WaitOne();
Console.WriteLine("foo");
Thread.Sleep(500); //simulate some work
Console.WriteLine("bar");
TimerMut.ReleaseMutex();
}
}
}
That doesn't work, "foos" still appear every second. How can I achieve this?
EDIT: You're right, it makes no sense to start a new thread to handle this. I thought only System.Threading.Timer is launched in a separate thread.
I'm not sure why you are using a new thread to start the timer, since timers run on their own thread, but here's a method that works. Simply turn the timer off until you are done with the current interval.
static System.Timers.Timer oTimer
public static void Main()
{
oTimer = new System.Timers.Timer();
oTimer.Elapsed += new ElapsedEventHandler(Handler);
oTimer.Interval = 1000;
oTimer.Enabled = true;
}
private void Handler(object oSource, ElapsedEventArgs oElapsedEventArgs)
{
oTimer.Enabled = false;
Console.WriteLine("foo");
Thread.Sleep(5000); //simulate some work
Console.WriteLine("bar");
oTimer.Enabled = true;
}
If you want to skip the tick if another is already working you can do this.
private readonly object padlock = new object();
private void SomeMethod()
{
if(!Monitor.TryEnter(padlock))
return;
try
{
//Do heavy work
}
finally
{
Monitor.Exit(padlock);
}
}
Easiest way I know of to do this kind of thing:
internal static volatile bool isRunning;
public static void Main()
{
Thread TT = new Thread(new ThreadStart(delegate()
{
System.Timers.Timer oTimer = new System.Timers.Timer();
oTimer.Elapsed += new ElapsedEventHandler(Handler);
oTimer.Interval = 1000;
oTimer.Enabled = true;
}));
TT.Start();
}
private void Handler(object oSource,
ElapsedEventArgs oElapsedEventArgs)
{
if(isRunning) return;
isRunning = true;
try
{
Console.WriteLine("foo");
Thread.Sleep(500); //simulate some work
Console.WriteLine("bar");
}
finally { isRunning = false; }
}
The handler still runs, but the very first thing it does is make sure that another handler isn't running, and if one is, it stops immediately.
For timers executing handlers more quickly (like 3-4 times a second), this has the possibility to race; two threads could proceed past the guard clause before one of them sets the bit. You can avoid this with a couple of lock statements, similar to a Mutex or Monitor:
static object syncObj = new object();
private void Handler(object oSource,
ElapsedEventArgs oElapsedEventArgs)
{
lock(syncObj)
{
if(isRunning) return;
isRunning = true;
}
try
{
Console.WriteLine("foo");
Thread.Sleep(500); //simulate some work
Console.WriteLine("bar");
}
finally { lock(syncObj) { isRunning = false; } }
}
This will ensure that only one thread can ever be examining or modifying isRunning, and as isRunning is marked volatile, the CLR won't cache its value as part of each thread's state for performance; each thread has to look at exactly the same memory location to examine or change the value.
You can follow the following pattern to skip doing the indicated work if another invocation of this method is still running:
private int isWorking = 0;
public void Foo()
{
if (Interlocked.Exchange(ref isWorking, 1) == 0)
{
try
{
//Do work
}
finally
{
Interlocked.Exchange(ref isWorking, 0);
}
}
}
The approach that you were using with a Mutex will result in addition ticks waiting for earlier ticks to finish, not skipping invocations when another is still running, which is what you said you wanted. (When dealing with timers like this its common to want to skip such ticks, not wait. If your tick handlers regularly take too long you end up with a giant queue of waiting handlers.)
I need to freeze the main thread until the end recursion.
Recursion depth = count of threads.
sample code:
BackgroundWorker backgroundWorker1;
Random ran;
private void Form1_Load(object sender, EventArgs e)
{
method();
label1.Text = "Threads is finished";
}
private void method() // recursive method
{
Thread.Sleep(100);
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerAsync(); //Beginning new thread
}
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
ran = new Random();
Thread.Sleep(ran.Next(500, 1000));
if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion
{
method();
}
}
When the threads are completed, label1.Text must have the value "Threads is finished". How is this done?
Console application PoC which caches references to all created workers and uses numeric variable to check how many workers still in progress, when this value reaches 0 - application terminates. Please let me know in case of any questions.
class Program
{
private static IList<BackgroundWorker> workers;
private static Random ran;
private static int activeWorkersCount;
static void Main(string[] args)
{
workers = new List<BackgroundWorker>();
DoWork();
while (activeWorkersCount > 0)
{
Thread.Sleep(200);
}
Console.WriteLine("Waiting for all workers to finish...");
Console.ReadLine();
}
private static void DoWork() // recursive method
{
Thread.Sleep(100);
var newWorker = new BackgroundWorker();
newWorker.DoWork += BackgroundWorkerDoWork;
newWorker.RunWorkerCompleted += (o, e) =>
{
Console.WriteLine("[E] Worker finished");
Interlocked.Decrement(ref activeWorkersCount);
};
Interlocked.Increment(ref activeWorkersCount);
newWorker.RunWorkerAsync();
}
private static void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("[S] Worker started");
ran = new Random();
Thread.Sleep(ran.Next(500, 1000));
if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion
{
DoWork();
}
}
}
When you decide it's time to stop recursion you can post a callback onto the GUI thread. Off the top of my head it'll be something like this:
if(ran.Next(1,5)!=1)
{
method();
}
else
{
Action action=()=>label1.Text = "Threads is finished";
this.BeginInvoke(action);
}
1) Create a method to update Label1:
private void WorkFinished()
{
if(Label1.InvokeRequired)
{
Label1.Invoke(WorkFinished);
}
else
{
Label1.Text = "Threads is finished";
}
}
2) Call WorkFinished() from backgroundWorker1_DoWork.
You can use CountDownEvent class:
Example:
using (CountDownEvent countdownEvent = new CountdownEvent(numberOfThreads))
{
for (int threadIndex= 0; i < numberOfThreads; threadIndex++)
ThreadPool.QueueUserWorkItem(
th =>
{
DoWork();
countdownEvent.Signal();
}, threadIndex);
countdownEvent.Wait();
}
Console.WriteLine("All threads complete");
I did it using a volatile integer number and it works well.
BackgroundWorker backgroundWorker1;
Random ran;
long runningThreads = 0;
public void Start()
{
method();
// Console.WriteLine("Threads is finished");
}
private void method() // recursive method
{
Interlocked.Increment(ref runningThreads);
Console.WriteLine("New thread started");
Thread.Sleep(100);
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerAsync(); //Beginning new thread
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ran = new Random();
Thread.Sleep(ran.Next(500, 1000));
if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion
{
method();
}
Finished();
}
private void Finished()
{
Interlocked.Decrement(ref runningThreads);
if (Interlocked.Read(ref runningThreads) == 0)
{
Console.WriteLine("Threads is finished");
}
}
I'm attempting to make a "simple" timer from 15 minutes to 0 seconds. I'm using 900 seconds as my 15 minutes. When I Run the program it runs through fine but Continues going into the negatives. I'm still a novice at C#. I'm wanting the code to stop at 0 and run an alert to grab someone's attention. Here is what I have thus far
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
namespace GBS_GI_Timer
{
public class Program
{
public static int t = 2;
public static void Main()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
//Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
//GC.KeepAlive(aTimer);
if (t == 0)
aTimer.Stop();
}
public static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//TimeSpan timeRemaining = TimeSpan.FromSeconds(t);
Console.WriteLine("Time remianing..{0}", t);
t--;
if (t == 0)
{
Console.WriteLine("\a");
Console.WriteLine("Time to check their vitals, again!");
Console.WriteLine("Press any key to exit...");
}
// Console.ReadKey();
Console.ReadLine();
}
}
}
You have it coded so that when you hit enter (or type something and hit enter), it then checks t and may stop the timer. You're checking if t == 0 and only then stopping the timer. What happens if t is less than zero before you hit enter?
You would have to refactor your code as below to make it work, System.Timers.Timer used ThreadPool to run the callback routines.
class Program
{
public static int t = 2;
static System.Timers.Timer aTimer = new System.Timers.Timer();
public static void Main()
{
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
Console.ReadLine();
}
public static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Time remianing..{0}", t);
t--;
if (t == 0)
{
Console.WriteLine("\a");
Console.WriteLine("Time to check their vitals, again!");
Console.WriteLine("Press any key to exit...");
aTimer.Stop();
Console.ReadLine();
}
}
}
There are some other logic issues with your program as it stands, and I am not certain it would do what you want even if it was running, though.
I would refactor your OnTimedEvent to just do
Console.WriteLine(string.Format("{0} time to check their vitals!"));
and use a while loop to check the status of t in the main routine.
You could also change the Timer.Interval when entering the handler so that no other events fire until they acknowledge the first event, but then you couldn't guarantee that this routine runs for 15 minutes...