在Unity中使用协程访问SQLite数据库

3
我在Unity中创建了一个菜单,其中填充了来自SQLite数据库的结果。但是当我创建菜单时,整个游戏会在查询数据库时暂停一会儿。
为了解决这个问题,我正在尝试将菜单的创建和填充数据分开(也就是说,在查询完成之前,菜单将只显示“加载中”)。
我一直在尝试使用yield-return协程来实现这一点,但游戏仍然会冻结。下面是一些伪代码,说明我正在做什么...
void createMenu () {

    // code to create menu... 

    StartCoroutine(getData());

}

IEnumerator getData () {

    List<string> sqlResults = Database.query("SELECT * FROM table");

    yield return null;

    updateMenu();

}

void updateMenu() {

   // replaces "loading" strings with sql data results 

}

我这样做是错的吗?还是我在错误地使用协程?

3个回答

4
看起来数据库操作正在阻塞主线程。使用 ThreadPool.QueueUserWorkItem 函数在一个新的线程中运行它。当它完成后,使用 这个 帖子中的 UnityThread.executeInUpdate 函数调用 updateMenu() 函数。你需要从这个 帖子中获取 UnityThread 类以便使用此解决方案。
void Awake()
{
    UnityThread.initUnityThread();
}

void runQuery(string query)
{
    ThreadPool.QueueUserWorkItem(RunInNewThread, query);
}

private void RunInNewThread(object a)
{
    string query = (string)a;
    List<string> sqlResults = Database.query(query);


    //We are in another Thread. Use executeInUpdate to run in Unity main Thread
    UnityThread.executeInUpdate(() =>
    {
        updateMenu();
    });
}

用法:

runQuery("SELECT * FROM table");

那么你的意思是说在Unity中没有本地实现这个功能的方法? - aadu
你的评论没有意义。这个答案是“本地化”的。所以,从createMenu函数中调用runQuery("SELECT * FROM table");。它不应该阻塞或冻结Unity。如果不是这样,那么问题就在于updateMenu()函数,你也应该发布它。 - Programmer
我只是想说,为了让它工作,我必须包含那个人的整个UnityThread类。它足够长,可以作为外部DLL。 - aadu
lockstock 的回答应该可以工作,但它所做的事情与我做的相同,只是它比我的回答性能更低,因为它每次都创建新的 Thread 而不是使用 ThreadPool。此外,它不像我制作的 UnityThread 脚本那样是线程安全的,但它应该可以工作。 - Programmer
UnityThread 是由我编写的,它存在的目的是为了让你不必自己编写。它使在 Unity 中使用线程更加简单和安全。就这样。如果你不想使用它,你可以编写自己的包装器。它的主要目标是简化在 Unity 中使用线程的过程。 - Programmer

2

是的,将这段代码放在协程中不会改变任何东西。Unity是单线程的,但是只要在该线程中没有调用任何Unity函数,就可以启动一个单独的线程来执行一些工作。

尝试这个:

IEnumerator getData () {

    List<string> sqlResults;

    var thread = new System.Threading.Thread(() => {
        sqlResults = Database.query("SELECT * FROM table");
    };

    thread.Start();

    while(thread.IsAlive){
        yield return null;
    }

    updateMenu();
}

你的回答也解决了问题,但是@Programmer先回答了 :) - aadu
现在UnityThread似乎不再受支持,我试图使用async/await,但是这是不行的,所以这是一个不错的解决方法。更深入地思考,UnityThread可能已被Unity Job System取代,哎呀。 - Jacksonkr

0
所以这里的问题是你正在与服务器同步而不是异步,这将使你等待连接或查询(如果它给出了错误的内容或是错误的查询,你将等到httprequest或db请求超时)。 尝试使用异步函数而不是枚举器,或者使用带有异步函数调用的枚举器,这将让你在检索信息时保持在菜单上。

但它是一个SQLite数据库。没有涉及服务器吗?它只是访问一个数据库文件。 - aadu
你有写异步函数的示例链接吗?Unity文档没用。 - aadu
请查看以下链接:https://www.codeproject.com/Articles/1121822/Using-Async-Await-Task-Methods-With-SQL-Queries-NE - life.cpp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接