首页 > 解决方案 > 无法让线程和动画旋转工作

问题描述

这是我的控制:

在此处输入图像描述

我正在使用以下代码旋转它:

全局变量,bool IsTriangleAnimRunning = false; 其余代码:

public void AnimateTriangle()
        {
            var rotation = (int)((100 / 100d) * 45 * 1); // Max 45 degree rotation
            var duration = (int)(750 * (100 / 100d)); // Max 750ms rotation

            while (IsTriangleAnimRunning != false)
            {
                MyTriangle.Dispatcher.BeginInvoke(
               (Action)(() =>
               {
                   var anim = new DoubleAnimation
                   {
                       To = rotation,
                       Duration = new Duration(TimeSpan.FromMilliseconds(duration)),
                       AutoReverse = true
                   };

                   var rt = new RotateTransform();
                   MyTriangle.RenderTransform = rt;
                   rt.BeginAnimation(RotateTransform.AngleProperty, anim);

               }), DispatcherPriority.ContextIdle);

                Thread.Sleep(duration * 2);
            }
        }

触发动画的按钮的事件处理程序:

 public void HandleTriangleEvents(object sender, RoutedEventArgs a) 
        {
            Thread t_triagle = new Thread(new ThreadStart(this.AnimateTriangle));

            Button btn = (Button)sender;
            if (btn.Name == "btnStartTriangleAnim")
            {
                IsTriangleAnimRunning = true;
                btnStartTriangleAnim.IsEnabled = false;
                t_triagle.Start();
            }
            else
            {
                IsTriangleAnimRunning = false;
                btnStartTriangleAnim.IsEnabled = true;
                t_triagle.Abort();
            }
        }

它的行为不自然,因为当我停止它时,它会重置为正常位置。我假设它出于某种原因这样做,我无法理解。此外,由于某种原因,此代码不会让它持续运行,而只会运行一次。

所需的功能: 如果,我点击开始按钮,运行线程并继续旋转,同时线程正在运行。如果,我打,停,然后停在当前的旋转状态。如果我点击开始,再次运行线程并继续来回旋转。

--

使用 Task Async 测试,运行速度较慢且不重复。

  private async Task AnimateTriangle()
        {
            double rotation = 45d;
            double duration = 100d;

            var anim = new DoubleAnimation
            {
                To = rotation,
                Duration = TimeSpan.FromMilliseconds(duration),
                AutoReverse = true,
                RepeatBehavior = RepeatBehavior.Forever
            };

            var transform = MyTriangle.RenderTransform as RotateTransform;

            await Task.Factory.StartNew(() =>
            {
                while (IsTriangleAnimRunning != false)
                {
                    MyTriangle.Dispatcher.Invoke(() =>
                    {
                        if (transform == null)
                        {
                            transform = new RotateTransform();
                            MyTriangle.RenderTransform = transform;
                        }

                        transform.BeginAnimation(RotateTransform.AngleProperty, anim);

                    }, DispatcherPriority.ContextIdle);        

                    if (IsTriangleAnimRunning == false)
                    {
                        MyTriangle.Dispatcher.Invoke(() =>
                        {
                            if (MyTriangle.RenderTransform is RotateTransform)
                            {
                                var angle = transform.Angle; // current animated value
                                transform.Angle = angle;
                                transform.BeginAnimation(RotateTransform.AngleProperty, null);
                            }
                        }, DispatcherPriority.ContextIdle);
                    }
                }
            });
        }

标签: c#wpf

解决方案


您不需要启动线程。

启动一个永远运行的动画,直到你通过设置一个null动画来重置它。

在重置它之前,将目标属性的值显式设置为当前动画值。

重复使用现有的 RotateTransform,而不是在每次启动动画时重新分配一个。

private void StartButtonClick(object sender, RoutedEventArgs e)
{
    double rotation = 45d;
    double duration = 750d;

    var anim = new DoubleAnimation
    {
        To = rotation,
        Duration = TimeSpan.FromMilliseconds(duration),
        AutoReverse = true,
        RepeatBehavior = RepeatBehavior.Forever
    };

    var transform = MyTriangle.RenderTransform as RotateTransform;

    if (transform == null)
    {
        transform = new RotateTransform();
        MyTriangle.RenderTransform = transform;
    }

    transform.Angle = 0d;
    transform.BeginAnimation(RotateTransform.AngleProperty, anim);
}

private void StopButtonClick(object sender, RoutedEventArgs e)
{
    if (MyTriangle.RenderTransform is RotateTransform transform)
    {
        var angle = transform.Angle; // current animated value
        transform.Angle = angle;
        transform.BeginAnimation(RotateTransform.AngleProperty, null);
    }
}

推荐阅读