Я недавно сделал мою простую графическую библиотеку многопоточной. Теперь это быстрее - и симуляция сильно дрожит, как если бы разные места кэшировали старые данные позиции и затем применяли их после того, как они стали «устаревшими».
По сути, ящики двигаются, затем дергаются назад, затем двигаются, затем дергаются назад ... Пока еще нет столкновений, так что это не так.
Не уверен, какой код отправлять.
Спасибо.
Редактировать: Что бы это ни было, оно также вызывает скачки задержки.
Edit2:
TaskManager:
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();
}