【问题标题】:Time Wait Inside Method时间等待内部方法
【发布时间】:2012-02-28 22:39:36
【问题描述】:

我从不花太多时间在计时器和延迟上,所以我很确定我的代码做了一些非常丑陋的事情,但我无法找到解决方案。

好的...我有一个名为 AnimatorsPool 的类,它同时包含并处理许多 Animator 类。 Animator 只是一个简单的、基于计时器的控制移动器。

    public sealed class AnimatorsPool : IDisposable
    {
        private Boolean m_Disposed;
        private Boolean m_Stopped;
        private Boolean m_Waiting;
        private Int32 m_DelayBetween;
        private Int32 m_DelayStart;
        private List<Animator> m_Animators;
        private Stopwatch m_Stopwatch;

        public Boolean AnimationsFinished
        {
            get
            {
                foreach (Animator animator in m_Animators)
                {
                    if (!animator.AnimationFinished)
                        return false;
                }

                return true;
            }
        }

        public AnimatorsPool(Int32 delayBetween, Int32 delayStart)
        {
            m_Disposed = false;
            m_Stopped = false;
            m_Waiting = false;
            m_DelayBetween = ((delayBetween < 0) ? 0 : delayBetween);
            m_DelayStart = ((delayStart < 0) ? 0 : delayStart);
            m_Animators = new List<Animator>();
        }

        private void Wait(Int32 delay)
        {
            m_Stopwatch = Stopwatch.StartNew();

            m_Waiting = true;

            while (!m_Stopped && (m_Stopwatch.ElapsedMilliseconds <= delay))
                Application.DoEvents();

            m_Waiting = false;

            m_Stopwatch.Stop();
        }

        public void Add(Animator animator)
        {
            m_Animators.Add(animator);
        }

        public void Dispose()
        {
            if (!m_Disposed)
            {
                foreach (Animator animator in m_Animators)
                    animator.Dispose();

                m_Animators.Clear();
                m_Animators = null;

                m_Disposed = true;
            }

            GC.SuppressFinalize(this);
        }

        public void Start()
        {
            if (m_Animators.Count > 0)
            {
                if (m_DelayStart > 0)
                    Wait(m_DelayStart);

                m_Animators[0].Start();

                if (m_Animators.Count > 1)
                {
                    for (Int32 i = 1, length = m_Animators.Count; i < length; ++i)
                    {
                        if (m_DelayBetween > 0)
                            Wait(m_DelayBetween);

                        m_Animators[i].Start();
                    }
                }
            }
        }

        public void Stop()
        {
            m_Stopped = true;

            while (m_Waiting)
                Application.DoEvents();
        }
    }

在我的主窗体中,有时使用 AnimatorsPool,我使用以下代码:

        using (AnimatorsPool pool = new AnimatorsPool(100, (delayAction ? 100 : 0)))
        {
            m_AnimatorsPools.Add(pool);

            for (Int32 i = (controlsCount - 1); i >= 0; --i)
            {
                Animator animator = new Animator(controls[i], coordinates[i], 50);
                pool.Add(animator);
            }

            pool.Start();

            while (!pool.AnimationsFinished)
                Application.DoEvents();

            m_AnimatorsPools.Remove(pool);
        }

现在……一开始发生的事情是,如果我在 AnimatorsPool 仍在运行 Wait() 方法时退出程序,我的主窗体正在消失,但该进程仍在我的任务管理器中不确定地运行,因此. 所以我在我的主窗体中实现了一个 Dispose 覆盖:

    protected override void Dispose(Boolean disposing)
    {
        if (!m_Disposed)
        {
            if (disposing)
            {
                s_RandomProvider.Dispose();

                foreach (AnimatorsPool pool in m_AnimatorsPools)
                    pool.Dispose();

                m_AnimatorsPools.Clear();
                m_AnimatorsPools = null;
            }

            m_Disposed = true;
        }

        base.Dispose(disposing);
    }

好的...现在我的程序有时可以正常退出,但有时不能。我从调试中可以看到,当它发生时,这是因为即使 m_Stopped 设置为 true,某些 AnimatorsPool 仍在运行 Wait() 方法。 我想我应该使用线程、计时器或类似的东西,但我没有经验。欢迎任何帮助!谢谢!

【问题讨论】:

    标签: c# .net multithreading timer while-loop


    【解决方案1】:

    无论你做什么,都不要这样做:

    while (!m_Stopped && (m_Stopwatch.ElapsedMilliseconds <= delay))
        Application.DoEvents();
    

    您应该为此使用计时器和事件驱动,而不是忙于等待。这只有在嵌入式实时产品中才可以。

    你需要重写你的代码,而且如果不创建计时器和事件驱动开发课程,就很难给你指点。

    编辑:来自 MSDN 中的 Application.DoEvents 文档(强调我的)

    调用此方法会导致当前线程在所有等待期间暂停 窗口消息被处理。如果一条消息导致一个事件被触发,那么 您的应用程序代码的其他区域可能会执行。 这可能会导致您的申请 表现出难以调试的意外行为。 如果您执行 需要很长时间的操作或计算,通常最好 在新线程上执行这些操作。有关异步的更多信息 编程,见Asynchronous Programming Overview

    【讨论】:

    • 我应该拆分我的 Start 方法以便使用两个带有 Tick 事件的计时器吗?
    • 编辑添加更多信息。
    猜你喜欢
    • 2020-02-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    相关资源
    最近更新 更多