0

i have a wpf form and a canvas in it and an image in canvas. i want this image to move randomly to directions every n milliseconds. i used while loop but it stocked in starvation. so i had no way to implement this movement by one mouse event to see how good is my idea about this movement. this is my code below:

public void movebox()
        {
            Random rnd = new Random();
            int movex = rnd.Next(0, 2);
            int movey = rnd.Next(0, 2);
            Canvas.SetTop(image1, Canvas.GetTop(image1) + (movey == 1 ? 1 : -1));
            Canvas.SetLeft(image1, Canvas.GetLeft(image1) + (movex == 1 ? 1 : -1));
        }
private void Window_MouseMove(object sender, MouseEventArgs e)
        {
            movebox();
        }

i likes movement of image but now i have same problem yet. i need this object to move automatically forever every n milliseconds without starvation. this is my ideal code below:

while(true){
                Random rnd = new Random();
                int movex = rnd.Next(0, 2);
                int movey = rnd.Next(0, 2);
                Canvas.SetTop(image1, Canvas.GetTop(image1) + (movey == 1 ? 1 : -1));
                Canvas.SetLeft(image1, Canvas.GetLeft(image1) + (movex == 1 ? 1 : -1));
                Thread.Sleep(1000);
            }

what should i have do now?

  • I have posted the answer according to your description. Then i thought maybe you want to do animation with this. What is the purpose of this movement? If it's animation there is a fairly good animation capabilities in WPF. – Emad Oct 12 '19 at 06:05

1 Answers1

1

One thing you can do if you really want a loop is to start another thread and use that. This way your UI will stay responsive.

public void movebox()
{
    Task.Run(() => 
    {
        while(true)
        {
            Random rnd = new Random();
            int movex = rnd.Next(0, 2);
            int movey = rnd.Next(0, 2);
            Dispatcher.Invoke(() => {
                Canvas.SetTop(image1, Canvas.GetTop(image1) + (movey == 1 ? 1 : -1));
                Canvas.SetLeft(image1, Canvas.GetLeft(image1) + (movex == 1 ? 1 : -1));
            });
            Thread.Sleep(1000);
        }
    });
}

A better approach however is to use Timer like this:

System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0,0,1);
dispatcherTimer.Start();


private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    Random rnd = new Random();
    int movex = rnd.Next(0, 2);
    int movey = rnd.Next(0, 2);
    Canvas.SetTop(image1, Canvas.GetTop(image1) + (movey == 1 ? 1 : -1));
    Canvas.SetLeft(image1, Canvas.GetLeft(image1) + (movex == 1 ? 1 : -1));
}

Disclaimer: I have written the code in browser.

Emad
  • 3,809
  • 3
  • 32
  • 44