【问题标题】:Implementing thread queue实现线程队列
【发布时间】:2012-02-10 20:42:56
【问题描述】:

考虑这个例子: 当用户点击一个按钮时,ClassA会快速触发OnUserInteraction事件10次。 ClassB 附加到此事件,并在其事件处理程序中触发 ClassC 的 Render 方法。在Render 方法中,AxisAngleRotation3D 被执行,但每个动画都持续 1 秒。

在这种情况下,所有 10 个 AxisAngleRotation3D 动画几乎同时执行,但我希望它们一个接一个地执行。据我了解线程,我可能必须在ClassB 中实现一个线程队列,其中AxisAngleRotation3DCompleted 事件表示允许触发下一个事件...?

这是正确的吗?我怎样才能做到这一点?

【问题讨论】:

    标签: c# wpf multithreading


    【解决方案1】:

    有一个任务队列。简单地说,有一个ConcurrentQueue<Func<bool>> 字段或类似字段,并根据需要向其中添加任务。然后让您的任务执行线程将Func<bool> 代表从队列中弹出并调用它们。如果他们返回真,他们就完成了。如果它们返回 false,请将它们重新添加到队列中,因为它们当时无法完成。

    这是一个例子:

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    
    namespace Example
    {
        public class TaskScheduler : IDisposable
        {
            public const int IDLE_DELAY = 100;
    
            private ConcurrentQueue<Func<bool>> PendingTasks;
            private Thread ExecuterThread;
            private volatile bool _IsDisposed;
    
            public bool IsDisposed
            {
                get { return _IsDisposed; }
            }
    
            public void EnqueueTask(Func<bool> task)
            {
                PendingTasks.Enqueue(task);
            }
    
            public void Start()
            {
                CheckDisposed();
    
                if (ExecuterThread != null)
                {
                    throw new InvalidOperationException("The task scheduler is alreader running.");
                }
    
                ExecuterThread = new Thread(Run);
                ExecuterThread.IsBackground = true;
                ExecuterThread.Start();
            }
    
            private void CheckDisposed()
            {
                if (_IsDisposed)
                {
                    throw new ObjectDisposedException("TaskScheduler");
                }
            }
    
            private void Run()
            {
                while (!_IsDisposed)
                {
                    if (PendingTasks.IsEmpty)
                    {
                        Thread.Sleep(IDLE_DELAY);
                        continue;
                    }
    
                    Func<bool> task;
                    while (!PendingTasks.TryDequeue(out task))
                    {
                        Thread.Sleep(0);
                    }
    
                    if (!task.Invoke())
                    {
                        PendingTasks.Enqueue(task);
                    }
                }
            }
    
            public void Dispose()
            {
                CheckDisposed();
                _IsDisposed = true;
            }
        }
    }
    

    【讨论】:

    • 我在哪里实例化这种类型的对象,在“ClassB”中?如果你明白我的意思,它会“一直运行”吗?
    • 在任何监督所有这一切的对象中实例化它——例如,一个表单。它会一直运行直到被处理掉。我可能应该解决这个问题。
    • 现在它会在空闲时每 100 毫秒检查一次新任务。
    • 谢谢,这正是我所需要的。但是一个问题导致另一个问题,如果您有空闲时间,这是我的下一个问题:stackoverflow.com/q/9241166/1110039 :)
    【解决方案2】:

    ClassB 可以将事件添加到队列中,然后一次渲染一个(可能使用计时器从队列中读取)。

    【讨论】:

      猜你喜欢
      • 2012-05-30
      • 2014-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 2010-10-22
      • 2013-07-24
      • 2010-12-10
      相关资源
      最近更新 更多