-1

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.

meisenman
  • 1,818
  • 1
  • 15
  • 25
  • There is no DispatcherTimer thread. This code runs on a single thread. – H H Jul 19 '13 at 18:37
  • Specify why you think the UI thread should wait. – H H Jul 19 '13 at 18:38
  • The value of x never changes between timer.start() and selPeople[x].IsCheck=false; I know this because my debugger returns the value of x as the default of -1 which I set at the top. I need the value of x to be captured in the TimerTick in order to remove it from the list after the method ends – meisenman Jul 19 '13 at 18:42
  • @HenkHolterman I need the main thread in the button press to wait until the timer method finishes and sets a value of x – meisenman Jul 19 '13 at 18:46
  • I don't see why you would use a Timer at all. – H H Jul 19 '13 at 18:48
  • Basically there people added to a list based on if their checkbox is checked. It goes through the TimerTick method and flashes between 40-60 times a random persons picture with a delay of (60 milliseconds in this case) It replicates flipping randomly through pictures and stopping at one at the end when index = max index. The timer is purely for Delay (thread.sleep was not a viable option for this) – meisenman Jul 19 '13 at 18:52
  • In this instance, I need to run through the timer with 4 choices of pictures. Select one and show it on the first grid. Then I need to remove the first one from the list so the last three can be randomly chosen between. This app replicates choosing random teams between 4 people. – meisenman Jul 19 '13 at 18:55
  • Then just use the Timer to finnish what the Button started. Do not 'wait' on anything. Disable the Button or block the action with a bool. – H H Jul 19 '13 at 18:57

1 Answers1

0

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.

Mehrdad Kamelzadeh
  • 1,764
  • 2
  • 21
  • 39
  • I am going to try just sleeping the thread manually in a loop although when I tried this in first mock up version with just one person being selected I had trouble and was told it is due to the thread.sleep – meisenman Jul 19 '13 at 19:02
  • If you use `Thread.Sleep` in the UI thread, that would freeze the UI and you will have the problem with that. But with the way I have just already said, you won't have any problem. I strongly recommend the link I gave you – Mehrdad Kamelzadeh Jul 19 '13 at 19:08
  • Oh you are putting TimerTick in a different thread. If that is the case wouldn't I need to invoke the displayImage... – meisenman Jul 19 '13 at 19:14
  • There are many things wrong in this code, for one it would cause cross thread exceptions when accessing `minSelTextBlock.Text`. – Scott Chamberlain Jul 19 '13 at 19:17
  • the mechanism of `async/await` is somehow complicated. but for now imagine it is in different thread. The important thing is it doesn't freeze your UI. It just waits on the line that calls the `Task` and the rest of your instance is responsive simultaneously. Again google that and read that link to have more information about it! – Mehrdad Kamelzadeh Jul 19 '13 at 19:21