在另一个线程(Unity3D)中从数据库中检索数据

本文关键字:数据库 检索 数据 另一个 线程 Unity3D | 更新日期: 2023-09-27 17:54:01

我目前有一个代码,从数据库中检索数据,并在unity3D中可视化。但是,每次它在fixeduupdate()函数中检索数据时,每隔1秒就会急剧增加一次。我正在考虑使用线程来做到这一点,但我不确定我做错了什么。

这是我在线程中调用的函数

 public void retrievefromDB(){
                            if (timeStep - prevTimeStep > 99) {
                                    timeStep -= 1; //special for this dataset
   query = "SELECT * FROM GridData2 WHERE timestep=" + timeStep;
                                    if (showParent)
                                            query += " AND (Level != 10)";
                                    else
                                            query += " AND (Level == 10)";
      query += " AND temperature >= " + minTemp + " AND temperature <= " + maxTemp;
                                    dt.Rows.Clear ();
                                    dt = sqlDB.ExecuteQuery (query);
                                    prevTimeStep = timeStep;
                            }
            }

这段代码每1秒延迟一次,因此我试图把它放到一个线程中。

void FixedUpdate()
    {
    Thread testthread = new Thread(new ThreadStart(retrievefromDB));
        testthread.Start ();
}

将其放入线程后,它会在一段时间后继续崩溃场景。谁能告诉我我做错了什么吗?怎么解呢?

在另一个线程(Unity3D)中从数据库中检索数据

最初问题的原因比较明显:数据库访问速度慢。如果你在FixedUpdate方法中嵌入数据库调用,你将在数据库访问发生时暂停游戏的移动(如果你必须初始化连接,这可能需要一秒钟)。

你的线程代码的主要问题是,你开始一个新的线程每次FixedUpdate被称为。这意味着你每秒启动60个新线程(默认情况下),这将很快削弱你的游戏!虽然在Unity中使用c#线程来完成这类工作是很好的,但更好的方法是创建一个单个线程,并允许它来管理时间,而不是每次作业运行时创建一个新线程。这意味着在Awake()Start()中创建线程,然后使用Thread.Sleep或类似的方法来处理计时。

协程(正如Mihai在他的回答中建议的那样)非常适合修复事件的时间,但它们仍然在游戏线程上运行:如果你将DB代码放在协程中,你仍然会在运行时看到暂停。如果你必须每秒运行这个数据库访问,你需要在一个合适的线程中。

也就是说,您是否考虑过数据库访问可能是不必要的?性能更高的模型可能是预先缓存所有数据,并在需要时从内存中使用它。(如果数据是非常动态的,或者运行在像移动设备这样内存受限的环境中,这可能是不可能的…)

无论你做什么,你都需要停止每帧访问你的数据库。

你只需要每60或每帧一次的结果。您可以通过使用一个变量来轻松地实现这一点,在这个变量中,您可以将上次调用后经过的时间加起来。

关于Unity中的多线程,你有三个选择:

  • 用于Unity的多线程框架,如
    https://www.assetstore.unity3d.com/en/!/内容/7285

  • c#内置线程
    你需要注意不要从次级线程中调用Unity特定的API。发送像Vector3, Color等数据结构是可以的,但不要调用像GameObjects或Components这样的引用对象。
    https://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx

  • Unity 协程
    协程是Unity模拟多线程的方式。它是一个非常强大的工具,可以在同一个线程中异步运行
    http://docs.unity3d.com/Manual/Coroutines.html

using System.Threading.Tasks;  
public class Example
{
    void StartOnDifferentThread()
    {
        Task.Factory
            .StartNew(() =>
            {
                FunctionToRun();
            })
            .ContinueWith(task =>
            {
                if (task.IsCompleted)
                {
                    // handle result
                }
                else if (task.IsFaulted)
                {
                    // handle error
                }
            });
    }
    void FunctionToRun()
    {
        // do stuff
    }
}

现在终于可以工作了。只需要在retrievefromDB()

中添加这些
public void retrievefromDB(){
      while(true){
                            if (timeStep - prevTimeStep > 99) {
                                    timeStep -= 1; //special for this dataset
   query = "SELECT * FROM GridData2 WHERE timestep=" + timeStep;
                                    if (showParent)
                                            query += " AND (Level != 10)";
                                    else
                                            query += " AND (Level == 10)";
      query += " AND temperature >= " + minTemp + " AND temperature <= " + maxTemp;
                                    dt.Rows.Clear ();
                                    dt = sqlDB.ExecuteQuery (query);
                                    prevTimeStep = timeStep;
                            }
           Thread.Sleep(1);
               }
            }
然后写入Start()函数
testThread = UnityThreadHelper.CreateThread (() =>
                                                     {
            UnityThreadHelper.TaskDistributor.Dispatch (() => retrievefromDB ());
        });
        testThread.Start ();

我正在使用来自http://forum.unity3d.com/threads/unity-threading-helper.90128/所以你可以去看看。感谢所有帮助过我的人!:)