C#XNA多线程SpriteBatch.End()“对象引用未设置为对象的实例”

时间:2012-09-29 14:37:08

标签: c# multithreading exception xna spritebatch

我是多线程的新手,所以暂时搁置所有其他问题。我无法解决如何解决我的精灵批处理被更快的线程和下一个线程结束导致“对象引用未设置为对象的实例”。

哦,如果你能看到我的代码出现其他任何问题,请随意让我觉得自己像个白痴^^

spriteBatch.Begin();

// Draw Particles
List<Thread> threads = new List<Thread>();
for (int i = 0; i < CPUCores; i++)
{
    int tempi = i; // This fixes the issue with i being shared
    Thread thread = new Thread(() => DrawParticles(tempi + 1, CPUCores));
    threads.Add(thread);
    thread.Start();
}
foreach (var thread in threads)
{
    thread.Join();
}

// ..More Drawing Code..

spriteBatch.End(); // <-- This is where the program crashes

PS谁决定使用4个空格来表示代码而不是[code] [/ code]是个好主意? ¬_¬

2 个答案:

答案 0 :(得分:3)

您的问题来自SpriteBatch不是线程安全的事实。通过从多个线程写入一个sprite-batch,你就会破坏它。

SpriteBatchImmediate模式除外)有点像精灵的List(你不会从多个线程中访问其中一个,是吗?)还是一个缓冲区精灵。因此,对此可能的解决方案是为每个线程设置一个SpriteBatch。通过在线程内部调用Draw来填充每个精灵批处理“缓冲区”。

然后,因为你只能在主线程上绘制东西(即:你只能在主线程上调用GraphicsDevice.Draw*,这是SpriteBatch.End在内部调用的内容),等待你的工作线程完成每个批次的填充,然后从主线程中调用每个批次的End。这会将精灵绘制到屏幕上。

当然,如果你想绘制大量的粒子,更好的技术可能是将所有内容卸载到GPU上。 Here is an answer为您提供了如何做到这一点的粗略指导。

答案 1 :(得分:0)

图形设备一次只能由一个线程访问,而SpriteBatch不是线程安全的,所以你的绘制调用应该从主线程发送。

如果要优化代码以绘制更多对象,DrawInstancedPrimitives将更加清晰

http://blogs.msdn.com/b/shawnhar/archive/2010/06/17/drawinstancedprimitives-in-xna-game-studio-4-0.aspx

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.graphicsdevice.drawinstancedprimitives.aspx