here is what i want to do.
i'm using Xamarin Android and trying to make a 24hour count down timer.
the timer text should be updated every second
when the app relaunches it should continue with saved time.
DateTime timeStartedCountDown;
timer should calculate time from one point. (not runtime delay)
eg) what i want =
DateTime timeStartedCountDown;
every second
DisplayLeftTime(24 + (timeStartedCountDown - currentTime)) ? some like this
not what i want =
int timeElapsed;
every second
timeElapsed += 1;
text.Text = twentyFourHoursSec - timeElapsed
i'm not familiar with time & Threading sorry..
ps. android java code is fine!
This starts a timer the first time you open the app.
It recalls the startTime by using ISharedPreferences. And updates the date each second in the Thread.
public class MainActivity : Activity
{
DateTime startTime = DateTime.Now;
Thread thread;
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences (this);
ISharedPreferencesEditor editor = prefs.Edit ();
long memStartTime = prefs.GetLong ("startTime", 0);
if (memStartTime != 0) {
startTime = new DateTime (memStartTime);
} else {
editor.PutLong ("startTime", startTime.Ticks);
editor.Apply();
}
TimerUpdate ();
}
void TimerUpdate () {
if (thread == null) {
thread = new Thread (delegate () {
while (true) {
Thread.Sleep (1000);
DateTime curTime = DateTime.Now;
Console.WriteLine (curTime - startTime);
//Update your on screen textview.
}
});
thread.Start ();
}
}
}
Related
Read multiple stackoverflow, codeproject solution, could not integrate to my problem.
Have a datagrid in a usercontrol which is loaded in a window. Each DataRow in the DataGrid represents a timer setting.
Like:
timer name : Test 1 , Timer : 1h 3m
timer name : Test 2 , Timer : 2h 2m
timer name : Test 3 , Timer : 3h 1m
Selecting a row, clicking on the button Start, Starts the timer of that row. And with dispatcher tick event, it updates the grid I have done till this. Now I have to start another(or two or ...) timer which will do the same at the same time. I am stuck on this. Let me share what I have tried!
btnStartClickEvent in mainwindow.xaml.cs
if (btnStart.Content.ToString() == "Start")
{
if (_AUC == ActiveUserControl.Grid)
{
runningRow = (TaskGridData)_TG.dgEmployee.SelectedItem;
if (runningRow != null)
{
currentlyRunningID.Add(runningRow.ID);
btnStart.Content = "Stop";
//worker.RunWorkerAsync(runningRow);
StartTimer(runningRow);
}
}
}
else if (btnStart.Content.ToString() == "Stop")
{
btnStart.Content = "Start";
StopTimer();
}
private DateTime TimerStart { get; set; }
private void StartTimer(TaskGridData tgd)
{
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 0);
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
TimerStart = DateTime.Now;
dispatcherTimer.Start();
//worker.RunWorkerAsync();
//string etime = DateTime.Now.Second.ToString();
}
private void StopTimer()
{
dispatcherTimer.Stop();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
var currentValue = DateTime.Now - TimerStart;
runningRow.Duration = DurationValueToString(currentValue);
temp = (List<TaskGridData>)_TG.dgEmployee.ItemsSource;
foreach (TaskGridData item in temp)
{
if (item.ID == runningRow.ID)
{
item.Duration = DurationValueToString(DurationStringToVlaue(item.Duration) - DurationStringToVlaue(runningRow.Duration));
break;
}
}
//_TG.dgEmployee.ItemsSource = null;
//_TG.dgEmployee.ItemsSource = temp;
Thread NewThreadforStartProcessAfterTraining = new Thread(() => UpdateGrid());
NewThreadforStartProcessAfterTraining.IsBackground = true;
NewThreadforStartProcessAfterTraining.SetApartmentState(ApartmentState.STA);
NewThreadforStartProcessAfterTraining.Start();
}
private void UpdateGrid()
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
_TG.dgEmployee.ItemsSource = null;
_TG.dgEmployee.ItemsSource = temp;
}));
}
I know this code is for single timer. If I click a 2nd row and try to start timer, then it gets error in tick event, running row is found null.
I am wondering how can I keep this code and make it work for multiple timer. May be multithreading. A guide to do that, will be very helpful.
Thread NewThreadforStartProcessAfterTraining = new Thread(() => UpdateGrid());
NewThreadforStartProcessAfterTraining.IsBackground = true;
NewThreadforStartProcessAfterTraining.SetApartmentState(ApartmentState.STA);
NewThreadforStartProcessAfterTraining.Start();
All the above part where you start a new STA thread is unneeded and wrong in this context, since you can't update the visual tree in this way.
You can find a correct example of using a STA thread in one of my previous answers: https://stackoverflow.com/a/42473167/6996876
Try to understand the concept of thread affinity in WPF.
You simply need an UpdateGrid() where you have to delegate UI work to the dispatcher.
Furthermore, passing an argument to the Tick event is already explained here: https://stackoverflow.com/a/16380663/6996876
In your case you may want to change the current unique runningRow so that it's passed to the event instead.
I have started developing a quiz app that will have a 60 second count down for each question. I searched other issues but could not find my specific issue. When the first question is displayed the screen dsplays "60" and the countdown proceeds normally. However, when the second questions is generated (after a button click submit) the counter starts again, but this time uses 2 second intervals. Then when the third question generates after a click, it counts down in 3 second intervals! I then noticed that the timer display starts 1 second less in each question. (ex Question 1 starts with 60, Question 2 starts with 59......)
This is my first time using DispatcherTimer so I'm learning as I go. My goal is for the timer to always countdown in 1 second intervals.
public sealed partial class QuickPage : Page
{
DispatcherTimer timeLeft = new Dispatcher();
int timesTicked = 60;
public void CountDown()
{
timeLeft.Tick += timeLeft_Tick;
timeLeft.Interval = new TimeSpan(0,0,0,1);
timeLeft.Start();
}
public void timeLeft_Tick(object sender, object e)
{
lblTime.Text = timesTicked.ToString();
if (timesTicked > 0)
{
timesTicked--;
}
else
{
timeLeft.Stop();
lblTime.Text = "Times Up";
}
}
}
I then use a button click where if th user is right:
timeLeft.Stop();
timesTicked = 60
QuestionGenerator();
The Question Generator fucntion looks like this:
private void QuestionGenerator()
{
CountDownTimer();
if (iAsked < 6)
{
//Code to generate random question
}
}
Do not subscribe to the DispatcherTimer every time you call CountDown.
DispatcherTimer timeLeft;
int timesTicked = 60;
public QuickPage()
{
timeLeft = new Dispatcher();
timeLeft.Tick += timeLeft_Tick;
timeLeft.Interval = new TimeSpan(0,0,0,1);
}
private void QuestionGenerator()
{
timeLeft.Start();
if (iAsked < 6)
{
//Code to generate random question
}
}
I've written a simple schedule app which calculates 10 nearest scheduled bus arrivals depending on current time, and displays them in 10 textViews. Now what I need is to have the whole process repeat over and over every second and refresh the data.
Below is the class that is loaded after this delegate:
button1.Click += delegate
{
StartActivity(typeof(Schedule));
FullSchedule.MMain("route1_1_0");
};
namespace AndroidApplication7
{
[Activity(Label = "My Activity")]
public class Schedule : Activity
{
public System.Timers.Timer _timer;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Schedule);
TextView textView0 = FindViewById<TextView>(Resource.Id.textView0);
TextView textView1 = FindViewById<TextView>(Resource.Id.textView1);
TextView textView2 = FindViewById<TextView>(Resource.Id.textView2);
TextView textView3 = FindViewById<TextView>(Resource.Id.textView3);
TextView textView4 = FindViewById<TextView>(Resource.Id.textView4);
TextView textView5 = FindViewById<TextView>(Resource.Id.textView5);
TextView textView6 = FindViewById<TextView>(Resource.Id.textView6);
TextView textView7 = FindViewById<TextView>(Resource.Id.textView7);
TextView textView8 = FindViewById<TextView>(Resource.Id.textView8);
TextView textView9 = FindViewById<TextView>(Resource.Id.textView9);
TextView textView10 = FindViewById<TextView>(Resource.Id.textView10);
textView1.Text = FullSchedule.T[0];
textView2.Text = FullSchedule.T[1];
textView3.Text = FullSchedule.T[2];
textView4.Text = FullSchedule.T[3];
textView5.Text = FullSchedule.T[4];
textView6.Text = FullSchedule.T[5];
textView7.Text = FullSchedule.T[6];
textView8.Text = FullSchedule.T[7];
textView9.Text = FullSchedule.T[8];
textView10.Text = FullSchedule.T[9];
_timer = new System.Timers.Timer();
_timer.Interval = 1000;
_timer.Elapsed += OnTimedEvent;
_timer.Enabled = true;
}
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e)
{
RunOnUiThread(() => FullSchedule.MMain(FullSchedule.nname));
RunOnUiThread(() => StartActivity(typeof(Schedule)));
}
}
}
But there are two problems:
Every second it updates the view slews from the side as if it was opened (quite logical but I'm not quite sure of a different way of doing it).
After 5-10 seconds the app freezes and the screen is just blank.
I'll really appreciate any suggestions to how this updating can be accomplished.
Dmetrey.
It looks like you're creating a new activity on every timer interval, but at no point do you call Finish(). So you create an activity. 1 second later you create a second. 1 second later both activities create another one (4 activities total), 1 second later 8 activities, etc. Do you mean to do this?
I am using a design for playing wav files one after another. This design is based on mediaEnded event and works fine. When trying to imply this design on very short wav files, the mediaEnded event isn't always raised.
Is their a solution for this problem?
Thanks.
I implemented a workaround using a timer to periodically check for two situations:
Video Playback Position has not moved since last check - indicates the video is stuck.
Video Playback Position is beyond the end of the video - indicates the video is playing but usually just a black screen will be displayed.
If either condition exists force the next vide to start playing.
Note that this is an extract of code from a class file.
namespace XXXX
{
public partial class VideoWindow : Window
{
private DispatcherTimer mediaPositionTimer; // We check the play position of the video each time this fires to see if it has hung
double _lastPosition = -1;
int _video_count;
int videoDuration;
DateTime lastVideoStartTime;
public VideoWindow()
{
adMediaElement.LoadedBehavior = MediaState.Manual;
adMediaElement.MediaEnded += adMediaElement_MediaEnded;
adMediaElement.MediaOpened += adMediaElement_MediaOpened;
adMediaElement.MediaFailed += adMediaElement_MediaFailed;
}
// Increment the counter every time we open a video
void adMediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
Log("Media opened");
_video_count++;
}
// If we have a failure then just start the next video
void adMediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
Log("Media failed");
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
PlayNextMedia();
}));
}
// When a video ends start the next one
private void adMediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
Log("MediaEnded called");
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
PlayNextMedia();
}));
}
// Stops and Closes any existing video
// Increments the file pointer index
// Switches to display ads if no more videos
// else
// Starts the video playing
private void PlayNextMedia()
{
// Log(String.Format("PlayNextMedia called"));
//Close the existing file and stop the timer
EndVideo2();
adMediaElement.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
adMediaElement.Stop();
adMediaElement.Close();
}));
currentMediaFileIndex++;
if (currentMediaFileIndex > (mediaFileCount - 1))
{
Log(String.Format(" switching to Ads, currentMediaFileIndex = {0}", currentMediaFileIndex));
// Now setup and then run static adds for 10 minutes
currentMediaFileIndex = 0;
StartAds();
}
else
{
Log(String.Format(" switching media, index = {0}", currentMediaFileIndex));
adMediaElement.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
StartVideo2();
}));
}
}
// Stops the mediaPositionTimer, must be called in conjunction with a admediaElement.Pause() or Stop()
private void EndVideo2()
{
// Log("EndVideo2() called");
_is_playing = false;
// Stop the timer
if (mediaPositionTimer != null)
{
mediaPositionTimer.Stop();
}
}
// Load the media file
// Set the volume
// Set the lastVideoStartTime variable
private void StartVideo2()
{
// Log("StartVideo2() called");
loadMediaFile(currentMediaFileIndex);
adMediaElement.Volume = Properties.StationSettings.Default.VolumeMedia;
lastVideoStartTime = DateTime.Now; // Record the time we started
// Stop the timer if it exists, otherwise create a new one
if (mediaPositionTimer == null)
{
mediaPositionTimer = new DispatcherTimer();
// Set up the timer
mediaPositionTimer.Interval = TimeSpan.FromSeconds(10);
mediaPositionTimer.Tick += new EventHandler(positionTimerTick);
}
else
{
mediaPositionTimer.Stop();
}
// Start it running
adMediaElement.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
mediaPositionTimer.Start();
_is_playing = true;
adMediaElement.Play();
}));
}
private void RestartVideo2()
{
//Log("Restart the video");
adMediaElement.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
mediaPositionTimer.Start();
_is_playing = true;
adMediaElement.Play();
}));
}
// Check the playback position of the mediaElement has moved since the last check,
// if not then the video has hung
// Also check if the playback position exceeds the video duration,
// if so it has also hung
// If video has hung then force the next one to start and report a Warning
private void positionTimerTick(object sender, EventArgs e)
{
double duration;
double currentPosition = adMediaElement.Position.TotalSeconds;
if (adMediaElement.NaturalDuration.HasTimeSpan)
{
duration = adMediaElement.NaturalDuration.TimeSpan.TotalSeconds;
}
else
{
duration = 5 * 60; // Default to 5 minutes if video does not report a duration
}
if ((currentPosition == lastPosition) || currentPosition > (duration + 30))
{
// do something
//Log("*** Video position has exceed the end of the media or video playback position has not moved ***");
if (_is_playing)
{
String logString = String.Format("*** Video {0} has frozen ({1}c:{2}l:{3}d)so forcing the next one to start ***", mediaFiles[currentMediaFileIndex], currentPosition, lastPosition, duration);
Log(logString);
PlayNextMedia();
// Send a message indicating we had to do this
mainWindow.SendHeartbeat(MainWindow.STATUS_WARNING, logString);
}
}
lastPosition = currentPosition;
}
}
}
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);
}