【问题标题】:C# XNA Multi-threading SpriteBatch.End() "Object reference not set to an instance of an object"C# XNA 多线程 SpriteBatch.End() “对象引用未设置为对象的实例”
【发布时间】:2012-09-29 14:37:08
【问题描述】:

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

哦,如果您发现我的代码有任何其他问题,请随时让我觉得自己像个白痴^^

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] 是个好主意? ¬_¬

【问题讨论】:

  • 欢迎来到 StackOverflow :-) 帖子的格式使用 Markdown(我觉得这很不错),这就是 4 空格格式的来源。有关详细信息,请参阅stackoverflow.com/editing-help

标签: c# multithreading exception xna spritebatch


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    Graphics Device 一次只能被一个线程访问,并且 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

    【讨论】:

    • 有谁知道为什么我越来越卡顿并且使用多线程通常会降低 fps?使用 1 个线程,程序会阻塞大约 280k 个粒子,2 个线程 210k,3 个线程 180k。此外,绘图代码是目前仅使用 1 个核心的瓶颈,所以我仍然不了解多线程帧丢失和卡顿。我有一个 i5-2500k @ 4.0GHz、4x4GB 1600MHz RAM、HD 6870 1GB、256GB C4 SSD。
    • @catflier Instancing 对于精灵来说是一个非常糟糕的选择。如果这是一个不错的选择,SpriteBatch 将已经在内部使用该技术。当您有实际模型时,实例化会更好。但是你说你只能从主线程中绘制肯定是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多