WPF Dispatchertimer is not stopping, nor restarting - c#

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);
}

Related

wpf Multiple dispatch timer for timer application : Run multiple timer simulteniously

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.

How to return control of flow to a for loop?

I'm trying to code a loop to re execute a block of code 3 times. At the moment the code starts and executes once but doesn't repeat as intended with using the for loop.
I've set a break point on the for loop and it only goes through the loop once.
private async void startBtn_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
int i;
int roundMax = 3;
for (i = 1; i <= roundMax; i++)
{
//delay stop watch start to allow time to get ready.
TimeSpan time = TimeSpan.FromSeconds(1);
await System.Threading.Tasks.Task.Delay(time);
//set text box editing to false to prevent illegal input.
wrkTbx.IsEnabled = false;
restTbx.IsEnabled = false;
roundSlider.IsEnabled = false;
roundsTbx.IsEnabled = false;
StopGoCvs.Background = new SolidColorBrush(Colors.Green);
//startSoundElmt.Play();
// set up the timer
myTimer = new DispatcherTimer();
myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
myTimer.Tick += myTimer_Tick;
// start both timers
myTimer.Start();
myStopwatch.Start();
}
}
this is a logical issue, and I suspect it exits the for loop at some point, Assumming you're using Visual Studio, I would use Breakpoints at every steps and run the program to see where it fails, you may be missing a return or else somewhere

How to make a thread wait until another thread is finished to start

I am using a DispatcherTimer which calls a method to execute in a different thread. I am running a simple program that does not need to really worry about inefficiencies. How do I get the UI thread to wait for the DispatcherTimer to finish while still allowing the DispatcherTimer thread to make changes to the UI?
*I understand this may be semi repetitive however the examples I have seen are case specific. Thanks
private void spinButton_Click(object sender, RoutedEventArgs e)
{
minSelTextBlock.Text = "";
Index = 0;
maxIndex = rnd.Next(40, 60);
DispatcherTimer timer;
timer = new DispatcherTimer(DispatcherPriority.Normal);
timer.Interval = TimeSpan.FromMilliseconds(60);
timer.Tick += new EventHandler(TimerTick);
timer.Start();
selPeople[x].IsCheck = false;
displayCount++;
Index = 0;
maxIndex = rnd.Next(40, 60);
timer = new DispatcherTimer(DispatcherPriority.Normal);
timer.Interval = TimeSpan.FromMilliseconds(60);
timer.Tick += new EventHandler(TimerTick);
timer.Start();
selPeople[x].IsCheck = false;
displayCount++;
displayImage2b.Source = new BitmapImage(new Uri(selPeople[0].ImgPath));
}
private void TimerTick(object sender, EventArgs e)
{
minSelTextBlock.Text = "";
x = rnd.Next(0, selPeople.Count);
while (x == temp)
{
x = rnd.Next(0, selPeople.Count);
}
if (displayCount == 0)
displayImage1a.Source = new BitmapImage(new Uri(selPeople[x].ImgPath));
if (displayCount == 1)
displayImage2a.Source = new BitmapImage(new Uri(selPeople[x].ImgPath));
if (++Index >= maxIndex)
{
((DispatcherTimer)sender).Stop();
}
Index++;
temp = x;
}
Basically I need TimerTick to get the final x value before selPeople[x].IsCheck = false, because the whole point is to remove the item that was just selected from the list.
If you want the caller method to wait for the result of the method which is called, you can use Async/Await that is available in .Net 4.5
You can do something like this:
private async void spin()
{
minSelTextBlock.Text = "";
Index = 0;
maxIndex = rnd.Next(40, 60);
DispatcherTimer timer;
timer = new DispatcherTimer(DispatcherPriority.Normal);
timer.Interval = TimeSpan.FromMilliseconds(60);
timer.Tick += new EventHandler(StartTicker);
timer.Start();
selPeople[x].IsCheck = false;
displayCount++;
Index = 0;
maxIndex = rnd.Next(40, 60);
await Ticker();
selPeople[x].IsCheck = false;
displayCount++;
displayImage2b.Source = new BitmapImage(new Uri(selPeople[0].ImgPath));
}
Private Task<void> StartTicker()
{
Task.Run<void>(()=>Ticker());
}
private void Ticker()
{
while(your condition is true)
{
minSelTextBlock.Text = "";
x = rnd.Next(0, selPeople.Count);
while (x == temp)
{
x = rnd.Next(0, selPeople.Count);
}
if (displayCount == 0)
displayImage1a.Source = new BitmapImage(new Uri(selPeople[x].ImgPath));
if (displayCount == 1)
displayImage2a.Source = new BitmapImage(new Uri(selPeople[x].ImgPath));
if (++Index >= maxIndex)
{
break;
}
Index++;
temp = x;
Thread.Sleep(60);
}
}
Instead of Timer I have used a While Loop and Thread.Sleep() which is the same as your timer.
If you want to learn about async/await I really recommend this
Bye the way I haven't compiled this code. so it might have some syntax or other errors.

Can't Stop The DispacherTimer

I am writting some code in a wpf and I have a mouse that performs a click if the cursor stands still for a few seconds..I want to stop clicking if I open a new wpf window that i created...But it seems that dispachers doesn't stop, even if I tried almost everything...Is there any way??
public DispatcherTimer NewDispacher = new DispatcherTimer();
public DispatcherTimer NewDispacher2 = new DispatcherTimer();
public void CreateDispachers()
{
NewDispacher.Tick += new EventHandler(NewDispacher_Tick);
NewDispacher.Interval = new TimeSpan(0, 0, 0, 0, 10);
NewDispacher.Start();
NewDispacher2.Tick += new EventHandler(NewDispacher2_Tick);
NewDispacher2.Interval = new TimeSpan(0, 0, 0, 4);
NewDispacher2.Start();
}
public void NewDispacher_Tick(object sender, EventArgs e)
{
pointcur = GetCursorPosition();
}
public void NewDispacher2_Tick(object sender, EventArgs e)
{
pointdiff = GetCursorPosition();
if(form1opened==true)
{
NewDispacher.Stop();
NewDispacher = null;
NewDispacher2.Stop();
NewDispacher2 = null;
}
else if ((pointdiff.X >= pointcur.X - 5)
&& (pointdiff.X <= pointcur.X + 5)
&& (pointdiff.Y >= pointcur.Y - 5)
&& (pointdiff.Y <= pointdiff.Y + 5))
{
DoMouseClick();
pointcur.X = 0;
}
}
I make the bool Form1opened=true when the new Form is opened, but even if it gets into the if, dispachers doesn't stop...
Thanks in advance..
The fact is, Stop() *emphasized text*does*emphasized text* stop a DispatcherTimer in its tracks. So there must be an explanation elsewhere in your code. Perhaps you are restarting the timer somehow? Check when the code can execute that instantiates/starts the timers, in case it's getting called again unintentionally.

Thread.Sleep() in C#

I want to make an image viewer in C# Visual Studio 2010 which displays images one by one after seconds:
i = 0;
if (image1.Length > 0) //image1 is an array string containing the images directory
{
while (i < image1.Length)
{
pictureBox1.Image = System.Drawing.Image.FromFile(image1[i]);
i++;
System.Threading.Thread.Sleep(2000);
}
When the program starts, it stops and just shows me the first and last image.
Thread.Sleep blocks your UI thread use System.Windows.Forms.Timer instead.
Use a Timer.
First declare your Timer and set it to tick every second, calling TimerEventProcessor when it ticks.
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
myTimer.Tick += new EventHandler(TimerEventProcessor);
myTimer.Interval = 1000;
myTimer.Start();
Your class will need the image1 array and an int variable imageCounter to keep track of the current image accessible to the TimerEventProcessor function.
var image1[] = ...;
var imageCounter = 0;
Then write what you want to happen on each tick
private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs) {
if (image1 == null || imageCounter >= image1.Length)
return;
pictureBox1.Image = Image.FromFile(image1[imageCounter++]);
}
Something like this should work.
Yes, because Thread.Sleep blocks the UI thread during the 2s.
Use a timer instead.
If you want to avoid using Timer and defining an event handler you can do this:
DateTime t = DateTime.Now;
while (i < image1.Length) {
DateTime now = DateTime.Now;
if ((now - t).TotalSeconds >= 2) {
pictureBox1.Image = Image.FromFile(image1[i]);
i++;
t = now;
}
Application.DoEvents();
}

Categories