我最近使我的简单图形库多线程。现在速度更快了 - 而且模拟动作很多,好像各个地方已经缓存旧的位置数据,然后在它变得“陈旧”之后应用它。
基本上,盒子移动,然后猛拉回来,然后移动,然后猛拉回来......到目前为止还没有碰撞,所以不是那样。
不确定要发布的代码。
感谢。
编辑:无论是什么,也会导致延迟峰值。
EDIT2:
任务管理:
public class TaskManager
{
public delegate void MethodDel(float timestep);
private Queue<MethodDel> queue;
private List<TaskHandler> handlers;
private float value;
public float Value
{
get
{
return value;
}
set
{
this.value = value;
}
}
public TaskManager()
{
this.queue = new Queue<MethodDel>();
this.handlers = new List<TaskHandler>(System.Environment.ProcessorCount);
for (int t = 0; t < this.handlers.Capacity; ++t)
this.handlers.Add(new TaskHandler(this));
foreach (var handler in handlers)
handler.Start();
this.value = 0;
}
public void Start()
{
foreach (var handler in handlers)
handler.Wake();
}
public void Stop()
{
lock (queue)
queue.Clear();
foreach (var handler in handlers)
handler.StopWhenDone();
}
public void StopWhenDone()
{
foreach (var handler in handlers)
handler.StopWhenDone();
}
public void AddToQueue(MethodDel method)
{
lock (queue)
queue.Enqueue(method);
}
public bool GetFromQueue(out MethodDel method)
{
lock (queue)
{
if (queue.Count == 0) { method = null; return false; }
method = queue.Dequeue();
return true;
}
}
public int GetQueueCount()
{
return queue.Count;
}
public void Wait()
{
// Have to wait for them one at a time because the main thread is STA.
WaitHandle[] waitHandles = new WaitHandle[1];
// for (int t = 0; t < handlers.Count; ++t) waitHandles[t] = handlers[t].WaitHandle;
// WaitHandle.WaitAll(waitHandles);
for (int t = 0; t < handlers.Count; ++t) { waitHandles[0] = handlers[t].WaitHandle; WaitHandle.WaitAll(waitHandles); }
}
}
TaskHandler:
public class TaskHandler
{
private TaskManager manager;
private Thread thread;
private bool stopWhenDone;
private ManualResetEvent waitHandle;
public ManualResetEvent WaitHandle
{
get
{
return waitHandle;
}
}
public TaskHandler(TaskManager manager)
{
this.manager = manager;
}
public void Start()
{
waitHandle = new ManualResetEvent(false);
stopWhenDone = false;
thread = new Thread(Run);
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.MTA);
thread.Start();
}
public void StopWhenDone()
{
this.stopWhenDone = true;
}
private void Run()
{
TaskManager.MethodDel curMethod;
while (true)
{
while (!stopWhenDone || manager.GetQueueCount() > 0)
{
if (manager.GetFromQueue(out curMethod))
{
curMethod(manager.Value);
}
}
waitHandle.Set();
waitHandle.WaitOne();
}
}
public void Wake()
{
waitHandle.Set();
}
}
主要的更新循环:
public virtual void Update(float timestep)
{
taskManager.Value = timestep; taskManager.Start();
foreach (Camera camera in cameraLookup.Values)
// camera.Update(timestep);
taskManager.AddToQueue(camera.Update);
taskManager.StopWhenDone();
taskManager.Wait();
/* foreach (IAffector affector in affectorLookup.Values)
affector.Update(timestep); */
foreach (IAffector affector in affectorLookup.Values)
taskManager.AddToQueue(affector.Update);
taskManager.StopWhenDone();
taskManager.Wait();
// taskManager.StopWhenDone();
// taskManager.Wait();
foreach (IConstraint constraint in constraintLookup.Values)
// constraint.Update(timestep);
taskManager.AddToQueue(constraint.Update);
taskManager.StopWhenDone();
taskManager.Wait();
foreach (Physic physic in physicLookup.Values)
// physic.Update(timestep);
taskManager.AddToQueue(physic.Update);
taskManager.StopWhenDone();
taskManager.Wait();
foreach (Body body in bodyLookup.Values)
// body.Update(timestep);
taskManager.AddToQueue(body.Update);
taskManager.StopWhenDone();
taskManager.Wait();
foreach (Model model in modelLookup.Values)
// model.Update(timestep);
taskManager.AddToQueue(model.Update);
taskManager.StopWhenDone();
taskManager.Wait();
}
答案 0 :(得分:0)
您如何管理数据,是否可以在读取数据时进行测试以判断数据是否过时?提供有关多线程应用程序的建议非常困难。您可以尝试设置一些跟踪并记录您认为问题可能存在的具体部分。如果您在更改数据和读取数据时进行了记录,则可能能够找出出错的位置。
发布一些示例代码,向我们展示您如何管理数据,我们可以从那里获取数据。
答案 1 :(得分:0)
如果数据“过时”,那么您需要修复缓存系统以驱逐/更新旧数据。
线程真的不是那么难,逻辑很简单。线程问题是识别共享和未共享的数据,跟踪此数据,并确保以正确的顺序更新此数据。其中大部分与您的程序结构有关。在程序中添加线程时,结构要重要得多。