下载图像并将其保存到 Application.persistentDataPath 中挂起应用程序

Download and save image into Application.persistentDataPath hangs the app

我写了一个游戏,可以从服务器下载图片,然后将它们存储在 Application.persistentDataPath。

我的问题是在保存少量图像时场景挂起,保存完成后,它会执行其余代码。

我该如何解决这个问题?

正在将图像保存到设备本地存储中:

    if (File.Exists (Application.persistentDataPath + "/LayoutImages/")) {
        Debug.Log (imagesPathPrefix + " already exists.");
        return;
    }

    File.WriteAllBytes (Application.persistentDataPath + "/LayoutImages/abc.jpg", image);

您可以创建一个 Thread 来执行您的操作。这是一个例子:

class FileDownloader
{
    struct parameterObject
    {
        public string url;
        public string savePath;
    }

    static void downloadfunction(object data)
    {
        parameterObject obj = (parameterObject)data;

        if (File.Exists(obj.savePath))
            return;

        using (WebClient Client = new WebClient())
        {
            Client.DownloadFile(obj.url, obj.savePath);
        }
    }

    public static void downloadfromURL(string url, string savePath)
    {

        parameterObject obj = new parameterObject();
        obj.url = url;
        obj.savePath = savePath;

        Thread thread = new Thread(FileDownloader.downloadfunction);
        thread.Start(obj);

    }
}

注意:如果您要在下载后立即使用图像,请不要使用线程。 Unity3d 不是线程安全的。

您必须在后台执行此操作,以免锁定主线程。 但请记住,Unity API 不支持多线程,因此只能在此处完成其他 processes/calculations。所有 Unity API 调用都必须在后台任务完成后在主线程中进行。有很多方法可以做到这一点,比如后台工作者、线程、线程池等。

用线程做:

        new Thread(() => 
               {
        Thread.CurrentThread.IsBackground = true; 
        if (File.Exists (Application.persistentDataPath + "/LayoutImages/")) {
            Debug.Log (imagesPathPrefix + " already exists.");
            return;
        }

        File.WriteAllBytes (Application.persistentDataPath + "/LayoutImages/abc.jpg", image);

    }).Start();

或者使用线程池:

        System.Threading.ThreadPool.QueueUserWorkItem(delegate {
        if (File.Exists (Application.persistentDataPath + "/LayoutImages/")) {
            Debug.Log (imagesPathPrefix + " already exists.");
            return;
        }

        File.WriteAllBytes (Application.persistentDataPath + "/LayoutImages/abc.jpg", image);
    }, null);

我还没有测试过这些,但它们应该可以工作。

--- 已更新 (6 月 18 日)----

使用 AssetBundles 从服务器管理我的动态内容。


抱歉,但下面提供的 none 解决方案实际上有效,因为我已经尝试了所有这些解决方案,其中一些与我可以通过 Internet 找到的相似。

在一些研究中,这是我发现的:

"Basically, anything that UnityEngine makes available to you can't be touched in a thread you create with System.Threading."

"The only thing you can't do is use Unity API methods themselves across different threads, as they are not thread-safe, but that won't prevent you from doing background processing tasks."


我实际上"solved"这个问题。

应用程序只有在计算机上 运行s 时才会挂起,从服务器下载图像并将它们保存到 Application.persistentDataPath。

但是,它在构建时不会挂起,运行 在我的移动设备上,使用相同的代码。

在没有互联网连接中断的情况下,我检查了那些大图像是否已完全下载并很好地存储在 persistentDataPath 中。

尽管这对我来说不再是问题,但仍然感到尴尬和不愉快。

我希望遇到这个问题的人至少可以尝试我的方法,检查应用程序构建时是否 "hanged" 并且在您的设备上 运行 ,特别是将大图像文件保存到设备本地存储,而不是 运行ning 在您的计算机中。