문제

So here is the case. I have a winforms application which is a game. Naturally I want to put some animations like explosions when a bullet hits something. I've tried to achieve this by putting a .gif on my UI, waiting until the animation finishes and then deleting the Control, representing the .gif. I tried achieving that with this code:

public void AnimateAction(Actions Action, int PositionX, int PositionY)
        {
            Thread AnimationThread = null;
                AnimationThread = new Thread(new ThreadStart(() => AnimateAction(Action, PositionX, PositionY, 1500)));
                AnimationThread.Start();
        }

private void AnimateAction(Actions Action, int PositionX, int PositionY, int AnimationDuration)
        {
                Control ActionAnimation = UiHandler.GetInstance().CreateActionItem(Action, PositionX, PositionY);
                this.Controls.Add(ActionAnimation);
                ActionAnimation.BringToFront();

                Thread.Sleep(AnimationDuration);
                this.Controls.Remove(ActionAnimation);

        }

Looks fine, doesn't it? Well.. it is not. Whenever I try to run this code I get an InvalidOperationException thrown, which tells me that I cannot access objects created on other threads. After doing some research on SO and other sources I've realized that I am trying to make unsafe call using threads, which is bad. The way to get around this is to call Invoke() method. However, this causes my animation to be run on the SAME thread that the main window is running, so while the animation thread is sleeping I am forced to wait for the animation to finish before I can see other actions being executed in the UI. Of course, I want to be able to move around etc. while my animation is being animated. How do I achieve this?

도움이 되었습니까?

해결책

I didn't test this code but you have to check if the form itself requires an invoke. Invoke method assures that background thread is synchronized with the main thread. Plus I don't suggest you to use Thread.Sleep.

        public void AnimateAction(Actions Action, int PositionX, int PositionY)
        {
            Thread AnimationThread = null;
                AnimationThread = new Thread(new ThreadStart(() => AnimateAction(Action, PositionX, PositionY, 1500)));
                AnimationThread.Start();
        }

        private void AnimateAction(Actions Action, int PositionX, int PositionY, int AnimationDuration)
        {
            if (form.Controls.InvokeRequired)
            {
                form.Controls.Invoke(new Action(AnimateAction), Action, PositionX, PositionY);
             }
             else
             {
                Control ActionAnimation = UiHandler.GetInstance().CreateActionItem(Action, PositionX, PositionY);
                form.Controls.Add(ActionAnimation);
                ActionAnimation.BringToFront();
                form.Controls.Remove(ActionAnimation);
               }


        }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top