I'm trying to build a simple timeout with C# WPF.
public void start(){
answerTimer = new DispatcherTimer();
answerTimer.Tick += new EventHandler(answerTimer_Tick);
answerTimer.Interval = new TimeSpan(0,0,0,0,10);
answerTimer.Start();
}
private void answerTimer_Tick(object sender, EventArgs e)
{
...
}
This works but if I move the Window dragging it, the countdown stops and restart when I drop the Window.... how to avoid it?
Thanks.
try to put this
DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Render);
Related
I am making a WPF application that is similar to a video player. There is a MediaElement for the video, and a slider that is bound to the video. I also want the current timestamp to appear.
public MainWindow()
{
InitializeComponent();
DataContext = VideoViewModel;
ViewModel1.video_timestamp = "00:00:00:00";
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e) {
if ((VideoElement.Source != null) && (VideoElement.NaturalDuration.HasTimeSpan))
{
Slider1.Minimum = 0;
Slider1.Maximum = VideoElement.NaturalDuration.TimeSpan.TotalMilliseconds;
Slider1.Value = VideoElement.Position.TotalMilliseconds;
}
}
private void VidSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
ViewModel1.video_timestamp = TimeSpan.FromMilliseconds(Slider1.Value).ToString(#"hh\:mm\:ss\:ff");
VideoElement.Position = TimeSpan.FromMilliseconds(Slider1.Value);
DataContext = ViewModel1;
}
VidSlider_ValueChanged should update the textbox that shows the current video timestamp. So when a video is playing, this function is called every tick. When the user drags the thumb, this function is also called. The problem is that this seems to slow the application down especially when the video is long and when the user keeps on dragging the thumb quickly.
I am thinking about doing some Threading but I'm at a loss with the syntax since this some kind of click event(?) in XAML. Can I have some suggestions?
PS. I should display in milliseconds because this data will be used for another application later on.
I do not know how to solve this problem:
I want in my WPF Application something like a screensaver which pops up (let's say after 20 seconds) if you do not interact with the program. I tried researching, but I did not find anything and I do not know how to start. Does anyone have any tips for me?
You can for example start DispacherTimer and reset it if person move mouse or click something. In event check is time's up start new window/popup/dialog modal with screensaver, if person move mouse or click in screensaver close it and back to previous window.
Something about DispacherTimer you can find here:
WPF Timer Like C# Timer
or here https://msdn.microsoft.com/en-gb/library/system.windows.threading.dispatchertimer%28v=vs.90%29.aspx
You can do something like this then all you have to do is just set a timmer in the app.cs that resets.
private DispatcherTimer _timer;
protected override void OnStartup(StartupEventArgs e)
{
_timer = new DispatcherTimer();
_timer.Tick += Timer_Tick;
_timer.Interval = new TimeSpan(0,0,0,20,0);
_timer.Start();
EventManager.RegisterClassHandler(typeof(Window),Window.MouseMoveEvent, new RoutedEventHandler(Reset_Timer));
EventManager.RegisterClassHandler(typeof(Window), Window.MouseDownEvent, new RoutedEventHandler(Reset_Timer));
EventManager.RegisterClassHandler(typeof(Window), Window.KeyDownEvent, new RoutedEventHandler(Reset_Timer));
}
private void Timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("Ticked");
}
private void Reset_Timer(object sender, EventArgs e)
{
_timer.Interval = new TimeSpan(0,0,0,20,0);
}
This will reset the timer every time you move your mouse click your mouse or push any key in the window.
So I'm using the Kinect SDK to make an application, and it's going well! I'm trying to make a button take a picture, but I want the code taking the picture to be delayed so the people have time to pose. I've tried using System.Threading.Thread.Sleep(3000); but what happens is that the whole thing freezes (Yes I know that's what sleep does...) and it uses the first frame anyway. So now I'm trying to use a Timer and Timed Event, but keep getting errors due to the inability to make it static (Kinect thing).
public class Timer1
{
private System.Timers.Timer aTimer;
public void Main()
{
aTimer = new System.Timers.Timer(3000);
//This is where the problem is. I'm getting "Cannot access a non-static member of outer type 'KinectButton.MainWindow' via nested type 'KinectButton.MainWindow.Timer1'
aTimer.Elapsed += new ElapsedEventHandler(takepicture);
aTimer.Interval = 1000;
aTimer.Enabled = True;
}
}
[private void takepicture(object sender, ElapsedEventArgs e)
{
BitmapSource image = (BitmapSource)videoStream.Source;
image.Save(DateTime.Now.ToString("ddMMyyyy HHmmss") + ".jpg", ImageFormat.Jpeg);
}
private void button7_Click(object sender, RoutedEventArgs e)
{
//Here I'm also getting "'KinectButton.MainWindow.Timer1' does not contain a definition for 'Enabled'"
Timer1.Enabled = true;
}
private void Timer1_Tick(object sender, EventArgs e)
{
//Here I'm getting "'KinectButton.MainWindow.Timer1' does not contain a definition for 'Enabled'" again...
Timer1.Enabled = false;
}
Well, let me know if you guys can help!
I assume this is a WPF app? I think you will want to use Windows.Threading.DispatcherTimer instead
Private timer As New Windows.Threading.DispatcherTimer
timer.Interval = New TimeSpan(0, 0, 0, 1)
AddHandler timer.Tick, AddressOf timer_Tick
timer.Start()
Private Sub timer_Tick(ByVal Sender As Object, ByVal e As EventArgs)
'do something
End Sub
yeah i know its vb but it should be easy to convert
when I start the timer ..timel is incremented normally ..but as soon as I stop the timer i.e. call the click_TimerStop function and start the timer again...the timel variable is incremented by timel+=2..and when I repeat the process ..it is increased by timel+=3..and it goes on and on ...how do I correct this ?..
DispatcherTimer clktimer = new DispatcherTimer();
private void click_TimerStart(object sender, RoutedEventArgs e)
{
clktimer.Start();
clktimer.Interval =new TimeSpan(0,0,1);
clktimer.Tick +=clktimer_tick;
}
private int timel = 0;
private void clktimer_tick(object sender, object e)
{
timel++;
timerSecond.Text = timel.ToString();
}
private void click_TimerStop(object sender, RoutedEventArgs e)
{
clktimer.Stop();
}
add
clktimer.Tick -=clktimer_tick;
before
clktimer.Tick +=clktimer_tick;
you'll unsubscribe and subscribe to event, so only one handler will be active at a time
and It's better to call start() after you set all settings to timer
It's because you're continually adding the clktimer_tick event handler each time you start the timer. Initialize your timer somewhere where it will only be called once and not every time you start, because there's no need to keep setting the same settings each time.
I have been looking for a reason, but about every single topic on stackoverflow I could find suggested a busy UI as the reason.
I have very basic code, just for testings and it simply won't update the UI, even though I am sure it cannot be busy doing something else:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
static double t = 0;
static double dt = 0.1;
private void button1_Click(object sender, RoutedEventArgs e)
{
Timer timer = new Timer(5000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(Update);
timer.Start();
}
void Update(object sender, ElapsedEventArgs e)
{
t = t + dt;
testBlock1.Text = (t).ToString();
}
}
I debugged it and set a breakpoint to the textBlock1.Text update and it did break every 5 seconds, but the UI is never updated. As can be seen in the code, when I move my mouse over the Button I use to start the timer, the button shows its typical "mouse-over-button" animation. Why does that happen, but not the text update?
If anyone can lead me to a good topic on stackoverflow, please do so and I will delete my question here, but I couldn't find any topic explaining why this approach doesn't update the UI even though the UI is not busy doing anyting else.
System.Timers.Timer won't by default marshal back to the UI thread. In Windows Forms you can make it do so easily enough:
Timer timer = new Timer(5000);
timer.SynchronizingObject = this;
... but WPF UI elements don't implement ISynchronizeInvoke, which would stop this from working for you in WPF.
You could use the Dispatcher to marshal over to the UI thread within the handler, or you could just use a DispatcherTimer to start with.
For WPF, you should use DispatcherTimer -
Also with the above code you posted, i am getting a cross thread error since elapsed event is raised on other thread and not on UI thread.
private void button1_Click(object sender, RoutedEventArgs e)
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 5);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
t = t + dt;
txt.Text = (t + dt).ToString();
}
EDIT
Also, you can marshal it on UI Dispatcher with your existing code like this -
void Update(object sender, ElapsedEventArgs e)
{
App.Current.Dispatcher.Invoke((Action)delegate()
{
t = t + dt;
txt.Text = (t + dt).ToString();
});
}