The following dispatcher runs every 1 minute, counting from the time is invoked its Start() method...but what I actually need is that it ticks on every change in the minute component of the system time. Any idea?
This is a windows application (WPF).
DispatcherTimer hourTimer = new DispatcherTimer(DispatcherPriority.Normal)
{
Interval = new TimeSpan(0, 1, 0)
};
hourTimer.Tick += (sender,e) => { renderTime(); };
hourTimer.Start();
You can't get a "metronome quality beat" from any timer that uses a single thread to execute the tick. This is because the thread may be blocked when the tick needs to happen.
The best you can do is calculate the time till the next tick and reset the duration at the start of the tick event.
var now = DateTime.UtcNow;
var nextMinute = now.AddTicks(-(now.Ticks%TimeSpan.TicksPerMinute)).AddMinutes(1);
DispatcherTimer hourTimer = new DispatcherTimer(DispatcherPriority.Normal)
{
Interval = nextMinute - DateTime.UtcNow
};
hourTimer.Tick += (sender, e) =>
{
var correctionNow = DateTime.UtcNow;
var timeCorrection = correctionNow.AddTicks(-(correctionNow.Ticks % TimeSpan.TicksPerMinute)).AddMinutes(1);
hourTimer.Interval = timeCorrection - DateTime.UtcNow;
renderTime();
};
hourTimer.Start();
Related
I want the user to be able to chose the time the ClearFiles() function will get called every day. The timer executes at the time the user selects but never correctly fires after the x amount of minutes / hours specified.
Code:
DateTime nowTime = DateTime.Now;
DateTime deleteTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day,
FileFilter.deleteTime.Hour, FileFilter.deleteTime.Minute, 0);
if (nowTime > deleteTime)
{
deleteTime = deleteTime.AddDays(1)
}
double tickTime = (deleteTime - nowTime).TotalMilliseconds;
aTimer = new Timer(tickTime);
aTimer.Elapsed += (s, e) => ClearFiles(FileFilter.pathName);
aTimer.Start();
Hey I have an rather specific issue.
I am building an metronom, and this metronom also shows boxes, which will change their color in the given tact in bpm. the highest possible bpm is 400bpm with 4/4 beats. that means the fastest change of color should happen every: 37,5 ms.
The change of color will last some milliseconds.
Until now i tried to realize that with a timer:
timer = new System.Timers.Timer() { AutoReset = true, SynchronizingObject = null };
private async void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
boxViewLast = (BoxView)beatDisplay.Children[(int)lastI];
boxView = (BoxView)beatDisplay.Children[(int)i];
boxViewLast.Color = boxColor;
boxView.Color = transColor;
await Task.Delay((int)BeatMilliseconds);
boxView.Color = boxColor;
lastI = i;
i++;
if (i >= numOfChildren)
{
i = 0;
}
timer.AutoReset = Tempo == 1 && Play;
}
But in the UI I see a flickering some times if the color is changing fast and sometimes it is not even changing. I guess that resources are getting blocked and so the change can not be fullfilled in the given time. Is there a way to have UI change async and very performant? But I also need a very pricise timer
No reason to await Task.Delay inside the callback. You can use the timer to define the interval between callbacks:
var lastTime = DateTime.Now;
var times = new List<TimeSpan>(1000);
var timer = new System.Timers.Timer() { Enabled = true, Interval = 32, AutoReset = true};
timer.Elapsed += TimerHandler;
Console.WriteLine("Starting timer");
timer.Start();
await Task.Delay(TimeSpan.FromSeconds(3));
timer.Stop();
foreach (var time in times)
{
Console.WriteLine($"{time.TotalMilliseconds}ms passed");
}
void TimerHandler(object? sender, System.Timers.ElapsedEventArgs e)
{
TimeSpan timePassed = e.SignalTime - lastTime;
times.Add(timePassed);
lastTime = DateTime.Now;
}
It's going to be somewhat accurate:
30.5771ms passed
31.0725ms passed
30.8268ms passed
31.0783ms passed
30.5758ms passed
31.4693ms passed
31.0038ms passed
32.1051ms passed
31.0289ms passed
31.1313ms passed
30.9087ms passed
31.0877ms passed
31.9015ms passed
30.7389ms passed
46.8875ms passed
31.4987ms passed
31.7549ms passed
I want a DispatcherTimer to restart everytime the conditions are not met. Only when the if-condition is met for 5 seconds, the method can continue.
How should I stop the Dispatchertimer? The timeToWait variable is set to 3000, that works as intended.
Below is the code in C#. It is not responding as I want. It only starts, but never stops or restarts. I am making a WPF application.
dispatcherTimerStart = new DispatcherTimer();
if (average >= centerOfPlayingField - marginOfDetection && average <= centerOfPlayingField + marginOfDetection)
{
dispatcherTimerStart.Interval = TimeSpan.FromMilliseconds(timeToWait);
dispatcherTimerStart.Tick += new EventHandler(tick_TimerStart);
startTime = DateTime.Now;
dispatcherTimerStart.Start();
} else
{
dispatcherTimerStart.Stop();
dispatcherTimerStart.Interval = TimeSpan.FromMilliseconds(timeToWait);
}
private void tick_TimerStart(object sender, EventArgs args)
{
DispatcherTimer thisTimer = (DispatcherTimer) sender;
thisTimer.Stop();
}
you need to preserve the dispatcherTimer that enter your if block because in your else block you are stopping the new instance of DispatcherTimer not the one that entered the if block.
take a class level field
DispatcherTimer preservedDispatcherTimer=null;
var dispatcherTimerStart = new DispatcherTimer();
if (average >= centerOfPlayingField - marginOfDetection && average <= centerOfPlayingField + marginOfDetection)
{
**preservedDispatcherTimer = dispatcherTimerStart;**
dispatcherTimerStart.Interval = TimeSpan.FromMilliseconds(timeToWait);
dispatcherTimerStart.Tick += new EventHandler(tick_TimerStart);
startTime = DateTime.Now;
dispatcherTimerStart.Start();
}
//use preservedDispatcherTimer in else
else if(preservedDispatcherTimer!=null)
{
preservedDispatcherTimer.Stop();
preservedDispatcherTimer.Interval = TimeSpan.FromMilliseconds(timeToWait);
}
In my Windows Phone 7 app, I want ContentPanel's background to change its color within a specified time (3 seconds in this case). Basically I want it to be "flashing".
But the problem is that the changes do not appear while the loop is working, the color changes only once, after the loop is done working. Why?
byte R;
TimeSpan ts = new System.TimeSpan(0, 0, 0, 3);
DateTime dt1 = new DateTime();
DateTime dt2 = new DateTime();
requirement = true;
while (requirement)
{
R = Convert.ToByte(0.5 * 255 * (1 + Math.Sin(DateTime.Now.Millisecond)));
ContentPanel.Background = new SolidColorBrush(Color.FromArgb(255, R, 125, 70));
dt1 = DateTime.Now;
dt2 = DateTime.Now;
dt2.Subtract(dt1);
if (dt2.Subtract(ts).CompareTo(dt1) > 0) requirement = false;
}
Is it even possible?
Looks like your loop is too tight.
Try this instead:
private DispatcherTimer _timer;
private void StartFlash()
{
_timer = new DispatcherTimer();
_timer.Interval = new TimeSpan(0,0,1);
_timer.Tick += (s,e) => ChangeColour;
}
private void StopFlash()
{
_timer = null;
}
private void ChangeColour() {
// Your colour changing logic goes here
ContentPanel.Background = new SolidColorBrush(Color.FromArgb(a,r,g,b));
}
Put that code in a class. Call StartFlash() somewhere. ChangeColour will execute every second.
You are asking for DateTime.Now way too fast so the difference will equate to 0 as DateTime's accuracy does not go as far as nanoseconds (Dates are marked by milliseconds from the unix epoch after all).
You might want to limit the while with more solid logic.
Try using the DispatcherTimer to do in async way.
The UI is not updated during your method execution, moreover if you work in the UI thread.
I am using WPF mediaelement for playing video. What I need is to cyclically play a video form x position to y position. Is there any way to achieve this without using timer and polling Position property?
You don't have to poll the position property, but you can set it to begin play at start position, start a timer and set the interval for the time difference.
TimeSpan startTime = TimeSpan.FromSeconds(45);
TImeSpan endTime = TimeSpan.FromSeconds(55);
int timeDifference = endTime.TotalSeconds - startTime.TotalSeconds;
mediaElement.Position = startTime;
Timer t = new Timer() { Interval = timeDifference * 1000, AutoReset = true };
t.Tick += (sender, e) { mediaElement.Position = startTime };
t.Start();