I need to reverse DispatcherTimer
public TestTimer()
{
Timer = new DispatcherTimer();
Timer.Interval = new TimeSpan(0, 0, 1);
Timer.Tick += TimerTick;
StartTimer();
}
private DispatcherTimer Timer;
private int _seconds;
public int Seconds
{
get { return _seconds; }
set
{
if(value > -1 && value < 61)
_seconds = value;
}
}
private int _minutes;
public int Minutes
{
get { return _minutes; }
set
{
if (value > -1 && value < 61)
_minutes = value;
}
}
private int _hours;
public int Hours
{
get { return _hours; }
set
{
if (value > -1 && value < 25)
_hours = value;
}
}
public void StartTimer()
{
Timer.Start();
}
public void StopTimer()
{
Timer.Stop();
}
private void TimerTick(object sender, EventArgs e)
{
if (Seconds > 59)
{
Seconds = 0;
Minutes++;
if (Minutes > 59)
{
Minutes = 0;
Hours++;
if (Hours > 23)
Hours = 0;
}
}
Seconds++;
TimeFormat = string.Format("{0:00}:{1:00}:{2:00}",
Hours, Minutes, Seconds);
}
I'm not sure what you're trying to do or for what purpose.
If you want counting then you can use the TimerTick event handler to elapse every second and to count, or more efficiently, use DateTime.Now when you start, and subtract DateTime.Now when finished to get a TimeSpan between them.
If you're counting down, you can use the same approach but subtract the elapsed number of ticks away from your start to get your current countdown value.
Related
I create a subclass of Forms.Timer, and I cannot stop this timer.
public class Clock : Timer
{
private int startTime;
private PictureBox one;
private PictureBox two;
private PictureBox three;
public Clock(Size _size) : base()
{ startTime = 0; initialComponent(_size); }
public Clock(int start_time, Size _size) : base()
{ startTime = start_time; initialComponent(_size); }
public Point Location
{
get { return three.Location; }
set
{
three.Location = value;
two.Location = new Point(value.X + three.Width, value.Y);
one.Location = new Point(value.X + three.Width + two.Width, value.Y);
}
}
private void initialComponent(Size _size)
{
......
}
public void Show()
{
int bits = startTime % 10;
int ten = (startTime % 100) / 10;
int hundred = (startTime % 1000) / 100;
one.Image = ImageLauncher.loadImage(bits, ImageLauncher.ImageType.Timer);
two.Image = ImageLauncher.loadImage(ten, ImageLauncher.ImageType.Timer);
three.Image = ImageLauncher.loadImage(hundred, ImageLauncher.ImageType.Timer);
}
protected override void OnTick(EventArgs e)
{
startTime++;
if (startTime > 999 || startTime < 0) return;
this.Show();
}
}
I create an object in form's constructor, the timer can start normally, but the Stop() method doesn't work. I've tried to create a method to set Timer.Enabled to false, but it is still going, more weird is I tried to reset interval with timer.Enabled in a same method, the interval has changed but timer still has not disbaled.
In constructor:
clock = new Clock(new Size(23 * 3, 38));
start:
if (!clock.Enabled) clock.Start();
method with stop:
private void gameOver(bool is_win)
{
clock.Stop();
showAll();
string winface = is_win ? "cool" : "sad";
ShortCutStart.Image = ImageLauncher.loadImage(winface, ImageLauncher.ImageType.Face);
ShortCutStart.Name = winface;
}
This is the code in Form1:
private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
PbsWheel pbsw = new PbsWheel(pbs, pb, e.Delta, pb.AnimateRate, label2);
}
In the bottom of form1 i have this class:
public class AnimatedPictureBox : PictureBox
{
List<string> imageFilenames;
Timer t = new Timer();
public AnimatedPictureBox()
{
AnimateRate = 100; //It's up to you, the smaller, the faster.
t.Tick += Tick_Animate;
}
public int AnimateRate
{
get { return t.Interval; }
set { t.Interval = value; }
}
public void Animate(List<string> imageFilenames)
{
this.imageFilenames = imageFilenames;
t.Start();
}
public void StopAnimate()
{
t.Stop();
i = 0;
}
int i;
private void Tick_Animate(object sender, EventArgs e)
{
if (imageFilenames == null) return;
Load(imageFilenames[i]);
i = (i + 1) % imageFilenames.Count;
}
}
Now in the new class i have the same class AnimatedPcitureBox and also this code:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WeatherMaps
{
class PbsWheel
{
public PbsWheel(AnimatedPictureBox[] pbs, AnimatedPictureBox pb, int delta, int speed,Label label2)
{
//if (leave == true)
//{
for (int i = 0; i < pbs.Length; i++)
{
if (delta > 0)
{
if (speed < 5000)
{
if (speed < 1000)
{
speed += 100;
label2.Text = (speed / (double)1000).ToString();
}
else
{
speed += 1000;
label2.Text = (speed / 1000).ToString();
}
}
}
else
{
if (speed > 1000)
{
speed -= 1000;
label2.Text = (speed / 1000).ToString();
}
else
if (speed <= 1000 && speed > 100)
{
speed -= 100;
label2.Text = (speed / (double)1000).ToString();
}
}
}
//}
}
public class AnimatedPictureBox : PictureBox
{
List<string> imageFilenames;
Timer t = new Timer();
public AnimatedPictureBox()
{
AnimateRate = 100; //It's up to you, the smaller, the faster.
t.Tick += Tick_Animate;
}
public int AnimateRate
{
get { return t.Interval; }
set { t.Interval = value; }
}
public void Animate(List<string> imageFilenames)
{
this.imageFilenames = imageFilenames;
t.Start();
}
public void StopAnimate()
{
t.Stop();
i = 0;
}
int i;
private void Tick_Animate(object sender, EventArgs e)
{
if (imageFilenames == null) return;
Load(imageFilenames[i]);
i = (i + 1) % imageFilenames.Count;
}
}
}
}
But when im doing in Form1 this line:
PbsWheel pbsw = new PbsWheel(pbs, pb, e.Delta, pb.AnimateRate, label2);
Im getting 3 errors on pbs and pb. And pbs and pb are AnimatedPictureBox type.
Error 11 Argument 1: cannot convert from 'WeatherMaps.Form1.AnimatedPictureBox[]' to 'WeatherMaps.PbsWheel.AnimatedPictureBox[]'
Error 12 Argument 2: cannot convert from 'WeatherMaps.Form1.AnimatedPictureBox' to 'WeatherMaps.PbsWheel.AnimatedPictureBox'
Error 10 The best overloaded method match for 'WeatherMaps.PbsWheel.PbsWheel(WeatherMaps.PbsWheel.AnimatedPictureBox[], WeatherMaps.PbsWheel.AnimatedPictureBox, int, int, System.Windows.Forms.Label)' has some invalid arguments
You actually have 2 separate classes for AnimatedPictureBox as you have them as internal classes inside Form1 and WeatherMaps. It doesn't matter that the code and name is the same - the classes are different.
It will be better for you to move it to a new class that is not sitting inside any other class. Preferably you can move it to its own file too.
well the error is clear.
there are two classes with the same name in different namespaces.
create a new file an put it there, use it in both form / PbsWeel
Another way on doing it is to create a custom control. By adding the custom control to your Form1, the Form1.Designer will do the things for you.
I am trying to wrap my head around threading in C# but I am having difficulty implementing this behavior.
I need a simple yes/no dialog that returns DialogResult.No when 30 seconds are passed.
What I've got so far is this:
Thread th = new Thread(() =>
{
try
{
result = message.ShowDialog();
}
catch (Exception)
{
}
});
th.Start();
Thread.Sleep(30000);
th.Abort();
When I select Yes or No on the dialog it still waits out the 30 seconds, I need the thread to stop when response is received.
This is probably a no brainer but I'm relatively new to C# and could really use some help on this.
You could use a Timer when you initialize your Form.
When the timer expired, you close your Form.
Timer time1 = new Timer();
time1.Elapsed += new ElapsedEventHandler(OnTimedEvent);
time1.Interval = 30000; // 30 secs
...
time1.Enabled = true; // Start the timer
message.ShowDialog();
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
// Close your Form
message.Close();
// Maybe you could set a variable, that indicates you, that the timer timed out
}
You have to overwrite ShowDialog() and ShowDialog(owner). When your show dialog will be called you start a timer and forward to the base.ShowDialog(). When the timer raises the tick event simply call Close().
Here an example implementation:
public partial class FormTimed : Form
{
private String _OriginalText;
private DateTime _StartTime;
private Timer _Timer;
public FormTimed()
{
InitializeComponent();
InitializeTimer();
Duration = TimeSpan.FromSeconds(10);
}
[DefaultValue(typeof(TimeSpan), "00:00:10")]
public TimeSpan Duration { get; set; }
public override string Text
{
get
{
return _OriginalText;
}
set
{
_OriginalText = value;
base.Text = value;
}
}
public void DisableTimer()
{
_Timer.Stop();
base.Text = _OriginalText;
}
public void ResetTimer()
{
_StartTime = DateTime.UtcNow;
_Timer.Start();
}
public new DialogResult ShowDialog()
{
StartTimer();
return base.ShowDialog();
}
public new DialogResult ShowDialog(IWin32Window owner)
{
StartTimer();
return base.ShowDialog(owner);
}
private void InitializeTimer()
{
_Timer = new Timer();
_Timer.Interval = 100;
_Timer.Tick += OnTimerTick;
}
private void OnTimerTick(object sender, EventArgs e)
{
var finishTime = _StartTime + Duration;
var remainingDuration = finishTime - DateTime.UtcNow;
if (remainingDuration < TimeSpan.Zero)
{
Close();
}
base.Text = _OriginalText + " (" + (int)remainingDuration.TotalSeconds + ")";
}
private void StartTimer()
{
_StartTime = DateTime.UtcNow;
_Timer.Start();
}
}
I have a list as below:
private List<DateTime> _result = new List<DateTime();
and I add values to it like
_result.Add(DateTime.Now);
The requirement is that each item which is added should be removed from the list within 5 minutes deadline.
I was thinking I could create a Timer which checks my list every e.g. 1 minute and find old items and remove them but I hoped there could be an easier way?
How to implement it?
Thanks
Here's my take on this:
public class DateWrapper
{
private ConcurrentBag<DateWrapper> list;
private DateTime time;
public DateTime Time
{
get { return time; }
}
private Timer timer;
public DateWrapper(ConcurrentBag<DateWrapper> _list, DateTime _time)
{
list = _list;
time = _time;
list.Add(this);
timer = new Timer();
timer.Interval = 300000; // 5 Minutes
timer.Tick += new EventHandler(Tick);
timer.Start();
}
private void Tick(object sender, EventArgs e)
{
list.Remove(this);
}
}
The above work for small list of item. With a too big list, you get too many timer... and performance would get hurt.
So, if you have to handle lot of items, here's a generic way to do it:
public class ExpirableList<T> : IList<T>
{
private volatile List<Tuple<DateTime, T>> collection = new List<Tuple<DateTime,T>>();
private Timer timer;
public int Interval
{
get { return timer.Interval; }
set { timer.Interval = value; }
}
private TimeSpan expiration;
public TimeSpan Expiration
{
get { return expiration; }
set { expiration = value; }
}
/// <summary>
/// Define a list that automaticly remove expired objects.
/// </summary>
/// <param name="_interval"></param>
/// The interval at which the list test for old objects.
/// <param name="_expiration"></param>
/// The TimeSpan an object stay valid inside the list.
public ExpirableList(int _interval, TimeSpan _expiration)
{
timer = new Timer();
timer.Interval = _interval;
timer.Tick += new EventHandler(Tick);
timer.Start();
expiration = _expiration;
}
private void Tick(object sender, EventArgs e)
{
for (int i = collection.Count - 1; i >= 0; i--)
{
if ((DateTime.Now - collection[i].Item1) >= expiration)
{
collection.RemoveAt(i);
}
}
}
#region IList Implementation
public T this[int index]
{
get { return collection[index].Item2; }
set { collection[index] = new Tuple<DateTime, T>(DateTime.Now, value); }
}
public IEnumerator<T> GetEnumerator()
{
return collection.Select(x => x.Item2).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return collection.Select(x => x.Item2).GetEnumerator();
}
public void Add(T item)
{
collection.Add(new Tuple<DateTime, T>(DateTime.Now, item));
}
public int Count
{
get { return collection.Count; }
}
public bool IsSynchronized
{
get { return false; }
}
public bool IsReadOnly
{
get { return false; }
}
public void CopyTo(T[] array, int index)
{
for (int i = 0; i < collection.Count; i++)
array[i + index] = collection[i].Item2;
}
public bool Remove(T item)
{
bool contained = Contains(item);
for (int i = collection.Count - 1; i >= 0; i--)
{
if ((object)collection[i].Item2 == (object)item)
collection.RemoveAt(i);
}
return contained;
}
public void RemoveAt(int i)
{
collection.RemoveAt(i);
}
public bool Contains(T item)
{
for (int i = 0; i < collection.Count; i++)
{
if ((object)collection[i].Item2 == (object)item)
return true;
}
return false;
}
public void Insert(int index, T item)
{
collection.Insert(index, new Tuple<DateTime, T>(DateTime.Now, item));
}
public int IndexOf(T item)
{
for (int i = 0; i < collection.Count; i++)
{
if ((object)collection[i].Item2 == (object)item)
return i;
}
return -1;
}
public void Clear()
{
collection.Clear();
}
#endregion
}
You can use background thread, which will be iterate through the list and remove unneeded elements.
public void RemoveDates()
{
var checkDatesTask= new Task(
() =>
{
while (!_cancelationTokenSource.IsCancellationRequested)
{
//TODO: check and delete elements here
_cancelationTokenSource.Token.WaitHandle.WaitOne(
TimeSpan.FromSeconds(
5));
}
},
_cancelationTokenSource.Token,
TaskCreationOptions.LongRunning);
checkDatesTask.Start();
}
p.s. I suggest you read more about async. operations.
I am trying to create an event that executes a function when a certain amount of time has changed. The timer is done by another code, it's supposed to call Plus(1), but will that change all timers (if I create multiple)? And this code is not actually working.
namespace #event
{
class Program
{
static void Main(string[] args)
{
Tick tijd = new Tick();
tijd.interval = 10;
tijd.TijdVeranderd += new EventHandler(Uitvoeren);
dynamic func = new Tick();
for (int i = 0; i < 100; i++)
{
func.Plus(1);
}
Console.ReadLine();
}
static void Uitvoeren(object sender, EventArgs e)
{
Console.WriteLine("Uitgevoerd!");
}
}
public class Tick
{
public event EventHandler TijdVeranderd;
public int interval;
private int tijd;
public void Plus(int i)
{
tijd += 1;
}
public int Verander
{
get { return this.tijd; }
set
{
this.tijd = value;
if (tijd == interval)
{
if (this.TijdVeranderd != null)
this.TijdVeranderd(this, new EventArgs());
tijd = 0;
}
}
}
public Tick() { }
}
}
EDIT: I don't want to use the .net timer, I want to create my own.
Just use .net timer like this:
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new System.Timers.ElapsedEventHandler(aTimer_Elapsed);
aTimer.Interval = 1000; //here you can set your interval
aTimer.Start();
Here you can catch the event and call other method:
void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//TODO: call your method like "Plus"
}
There seem to be a couple of errors in your code:
First of all, in Main, you are calling Plus() on a different instance of Tick than the one that you configured. Try using tijd.Plus(1) instead of func.Plus(1).
Also, in the implementation of Plus, when you increment the private variable tijd, the code associated with the property Verander does not get executed, so no events ever fire. To quickly fix, increment Verander instead of tijd.
namespace #event
{
class Program
{
static void Main(string[] args)
{
Tick tijd = new Tick();
tijd.interval = 10;
tijd.TijdVeranderd += new EventHandler(Uitvoeren);
for (int i = 0; i < 100; i++)
{
tijd.Plus(1);
}
Console.ReadLine();
}
static void Uitvoeren(object sender, EventArgs e)
{
Console.WriteLine("Uitgevoerd!");
}
}
public class Tick
{
public event EventHandler TijdVeranderd;
public int interval;
private int tijd;
public void Plus(int i)
{
Verander += 1;
}
public int Verander
{
get { return this.tijd; }
set
{
this.tijd = value;
if (tijd == interval)
{
if (this.TijdVeranderd != null)
this.TijdVeranderd(this, new EventArgs());
tijd = 0;
}
}
}
public Tick() { }
}
}
You can try with this code
private static System.Timers.Timer aTimer;
public static void Main()
{
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
I don't know why you wouldn't use a system timer, but here's an [untested] implementation of a timer that should do the trick:
class MyCrudeTimer : IDisposable
{
public event EventHandler Alarm ;
public TimeSpan Duration { get ; private set ; }
public bool AutomaticallyReset { get ; private set ; }
public bool IsRunning { get ; private set ; }
private Thread timerThread ;
private ManualResetEvent start ;
private void TimerCore()
{
try
{
while ( start.WaitOne() )
{
System.Threading.Thread.Sleep( Duration ) ;
Alarm( this , new EventArgs() ) ;
}
}
catch ( ThreadAbortException )
{
}
catch ( ThreadInterruptedException )
{
}
return ;
}
public MyCrudeTimer( TimeSpan duration , bool autoReset )
{
if ( duration <= TimeSpan.Zero ) throw new ArgumentOutOfRangeException("duration must be positive","duration") ;
this.Duration = duration ;
this.AutomaticallyReset = autoReset ;
this.start = new ManualResetEvent(false) ;
this.timerThread = new Thread( TimerCore ) ;
this.timerThread.Start() ;
return ;
}
public void Start()
{
if ( IsRunning ) throw new InvalidOperationException() ;
IsRunning = true ;
start.Set() ;
return ;
}
public void Stop()
{
if ( !IsRunning ) throw new InvalidOperationException() ;
IsRunning = false ;
start.Reset() ;
return ;
}
public void Dispose()
{
try
{
if ( this.timerThread != null )
{
this.timerThread.Abort() ;
this.timerThread = null ;
}
}
catch
{
}
return ;
}
}