如何追踪同步错误?

时间:2011-03-11 15:59:19

标签: c# multithreading synchronization

我最近使我的简单图形库多线程。现在速度更快了 - 而且模拟动作很多,好像各个地方已经缓存旧的位置数据,然后在它变得“陈旧”之后应用它。

基本上,盒子移动,然后猛拉回来,然后移动,然后猛拉回来......到目前为止还没有碰撞,所以不是那样。

不确定要发布的代码。

感谢。

编辑:无论是什么,也会导致延迟峰值。

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();
    }

2 个答案:

答案 0 :(得分:0)

您如何管理数据,是否可以在读取数据时进行测试以判断数据是否过时?提供有关多线程应用程序的建议非常困难。您可以尝试设置一些跟踪并记录您认为问题可能存在的具体部分。如果您在更改数据和读取数据时进行了记录,则可能能够找出出错的位置。

发布一些示例代码,向我们展示您如何管理数据,我们可以从那里获取数据。

答案 1 :(得分:0)

如果数据“过时”,那么您需要修复缓存系统以驱逐/更新旧数据。

线程真的不是那么难,逻辑很简单。线程问题是识别共享和未共享的数据,跟踪此数据,并确保以正确的顺序更新此数据。其中大部分与您的程序结构有关。在程序中添加线程时,结构要重要得多。