考虑这个例子:
当用户点击按钮时, ClassA
会快速触发OnUserInteraction
个事件10次。 ClassB
附加到此事件,并在其事件处理程序中触发 ClassC
的Render方法。在Render
方法中执行AxisAngleRotation3D
,但每个动画都持续1秒。
在这种情况下,几乎所有10个AxisAngleRotation3D
动画都会同时执行,但我希望它们能够一个接一个地执行。据我了解线程,我可能不得不在ClassB
中实现一个线程队列,其中Completed
的{{1}}事件表示允许下一个事件触发......?< / p>
这是正确的,我该如何实现?
答案 0 :(得分:3)
ClassB可以将事件添加到队列中,然后一次渲染一个(可能使用计时器从队列中读取)。
答案 1 :(得分:3)
拥有一个任务队列。简而言之,拥有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;
}
}
}