Reputation: 2107
I wrote a game that can download images from server and then store them inside Application.persistentDataPath.
My problem is when saving few images the scene hangs and when it is done saving, it executes the rest of the code.
How can I solve this issue?
Saving image into device local storage:
if (File.Exists (Application.persistentDataPath + "/LayoutImages/")) {
Debug.Log (imagesPathPrefix + " already exists.");
return;
}
File.WriteAllBytes (Application.persistentDataPath + "/LayoutImages/abc.jpg", image);
Upvotes: 3
Views: 6179
Reputation: 2107
--- Updated (18th June)----
Use AssetBundles to manage my dynamic contents from server.
Sorry but none of the below provided solution are actually work as I have tried all of them and some of them are similar that I could find via Internet.
During some research this is what I've found:
"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."
I have actually "solved" this issue.
The app will hang only when it runs on the computer, downloading the images from server and save them into Application.persistentDataPath.
However, it will not hang when it's built and run on my mobile devices, under the same codes.
Without Internet connection interruption, I've checked those large images are completely downloaded and stored nicely in the persistentDataPath.
Feel awkward and unpleasant even though it is not an issue to me anymore.
I wish those who encounter this issue can at least try my method, check if it is "hanged" when the app is built and run on your device, especially saving the large image files into the device local storage, instead running in your computer.
Upvotes: 1
Reputation: 1034
You can create a Thread
for performing your operation on the side. Here is an example :
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);
}
}
Note: If you will use your image as soon as you download, do not use threading. Unity3d is not thread safe.
Upvotes: 2
Reputation: 113
You'd have to do it in the background so it doesn't lock up the main thread. But keep in mind the Unity API does not support multithreading so only other processes/calculations can be done here. All the Unity API calls would have to made in the main thread after the background task finishes. There are allot of ways to do this like backgroundworkers, threads, threadPools etc.
Doing it with threads:
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();
Or with a threadpool:
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);
I haven't tested these but they should work.
Upvotes: 2