Android Unity - Load a file on background thread
I need to load a file in my application and since it is big ( around 250MB) I need to perform this loading off the main thread. What is more, because assets on Android are not stored in a regular directory, but a jar file, I need to use WWW or UnityWebRequest class.
I ended up with helper method like that:
public static byte ReadAllBytes(string filePath)
{
if (Application.platform == RuntimePlatform.Android)
{
var reader = new WWW(filePath);
while (!reader.isDone) { }
return reader.bytes;
}
else
{
return File.ReadAllBytes(filePath);
}
}
The problem is I cannot use it on background thread - Unity won't allow me to create WWW object there. How can I create a method like this, which will read those bytes on current thread?
c# unity3d
add a comment |
I need to load a file in my application and since it is big ( around 250MB) I need to perform this loading off the main thread. What is more, because assets on Android are not stored in a regular directory, but a jar file, I need to use WWW or UnityWebRequest class.
I ended up with helper method like that:
public static byte ReadAllBytes(string filePath)
{
if (Application.platform == RuntimePlatform.Android)
{
var reader = new WWW(filePath);
while (!reader.isDone) { }
return reader.bytes;
}
else
{
return File.ReadAllBytes(filePath);
}
}
The problem is I cannot use it on background thread - Unity won't allow me to create WWW object there. How can I create a method like this, which will read those bytes on current thread?
c# unity3d
add a comment |
I need to load a file in my application and since it is big ( around 250MB) I need to perform this loading off the main thread. What is more, because assets on Android are not stored in a regular directory, but a jar file, I need to use WWW or UnityWebRequest class.
I ended up with helper method like that:
public static byte ReadAllBytes(string filePath)
{
if (Application.platform == RuntimePlatform.Android)
{
var reader = new WWW(filePath);
while (!reader.isDone) { }
return reader.bytes;
}
else
{
return File.ReadAllBytes(filePath);
}
}
The problem is I cannot use it on background thread - Unity won't allow me to create WWW object there. How can I create a method like this, which will read those bytes on current thread?
c# unity3d
I need to load a file in my application and since it is big ( around 250MB) I need to perform this loading off the main thread. What is more, because assets on Android are not stored in a regular directory, but a jar file, I need to use WWW or UnityWebRequest class.
I ended up with helper method like that:
public static byte ReadAllBytes(string filePath)
{
if (Application.platform == RuntimePlatform.Android)
{
var reader = new WWW(filePath);
while (!reader.isDone) { }
return reader.bytes;
}
else
{
return File.ReadAllBytes(filePath);
}
}
The problem is I cannot use it on background thread - Unity won't allow me to create WWW object there. How can I create a method like this, which will read those bytes on current thread?
c# unity3d
c# unity3d
asked 2 days ago
Michał PowłokaMichał Powłoka
151113
151113
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
just put your while loop inside a CoRoutine and while your request is not done to a yield return. when it is done call a method where you want to use your data:
IEnumerator MyMethod()
{
var reader = new WWW(filePath);
while (!reader.isDone)
{
yield return; // <- use endofFrame or Wait For ore something else if u want
}
LoadingDoneDoData(reader.bytes);
}
void LoadingDoneDoData(bytes data)
{
// your Code here
}
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
add a comment |
I think you can use something like
public static async void ReadAllBytes(string filePath, Action<byte> successCallback)
{
byte result;
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
result = new byte[stream.Length];
await stream.ReadAsync(result, 0, (int)stream.Length);
}
// Now pass the byte to the callback
successCallback.Invoke();
}
(Source)
Than I guess you can use it like
TheClass.ReadAllBytes(
"a/file/path/",
// What shall be done as soon as you have the byte
(bytes) =>
{
// What you want to use the bytes for
}
);
I'm no multi-threading expert but here and also here you can find more examples and how to's for async - await with Unity3d.
Alternatively also the new Unity Jobsystem might be interesting for you.
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
@MichałPowłoka But why can't you use theFileStreamfor that? it returns you the raw bytes just like theWWWwould do ... but with the difference thatFileStreamcan be used async / threaded
– derHugo
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
|
show 5 more comments
I ended up with the following solution. I did not find a way to load raw file main thread, but I managed to load it in Coroutine and perform further (also heavy) operations on this file on a background Thread. I made a static method like this:
public static void ReadAllBytesInCoroutine(MonoBehaviour context, string filePath, Action<ReadBytesInCoroutineResult> onComplete)
{
context.StartCoroutine(ReadFileBytesAndTakeAction(filePath, onComplete));
}
private static IEnumerator ReadFileBytesAndTakeAction(string filePath, Action<ReadBytesInCoroutineResult> followingAction)
{
WWW reader = null;
try
{
reader = new WWW(filePath);
}
catch(Exception exception)
{
followingAction.Invoke(ReadBytesInCoroutineResult.Failure(exception));
}
while (reader != null && !reader.isDone)
{
yield return null;
}
followingAction.Invoke(ReadBytesInCoroutineResult.Success(reader.bytes));
}
ReadBytesInCoroutineResult is my simple, custom data class:
public class ReadBytesInCoroutineResult
{
public readonly bool successful;
public readonly byte data;
public readonly Exception reason;
private ReadBytesInCoroutineResult(bool successful, byte data, Exception reason)
{
this.successful = successful;
this.data = data;
this.reason = reason;
}
public static ReadBytesInCoroutineResult Success(byte data)
{
return new ReadBytesInCoroutineResult(true, data, null);
}
public static ReadBytesInCoroutineResult Failure(Exception reason)
{
return new ReadBytesInCoroutineResult(true, null, reason);
}
}
This way I have a mechanism to order to load a file in coroutine in any place (as long as it is on the main thread). A file is loaded synchronously, but it is not blocking main thread, because of the coroutine. Later I invoke this function and take acquired bytes on a separate thread, where I perform heavy computing on them.
ResourcesUtils.ReadAllBytesInCoroutine(monoBehavior, filePath, (bytes) => {
//here I run an async method which takes bytes as parameter
});
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54234452%2fandroid-unity-load-a-file-on-background-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
just put your while loop inside a CoRoutine and while your request is not done to a yield return. when it is done call a method where you want to use your data:
IEnumerator MyMethod()
{
var reader = new WWW(filePath);
while (!reader.isDone)
{
yield return; // <- use endofFrame or Wait For ore something else if u want
}
LoadingDoneDoData(reader.bytes);
}
void LoadingDoneDoData(bytes data)
{
// your Code here
}
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
add a comment |
just put your while loop inside a CoRoutine and while your request is not done to a yield return. when it is done call a method where you want to use your data:
IEnumerator MyMethod()
{
var reader = new WWW(filePath);
while (!reader.isDone)
{
yield return; // <- use endofFrame or Wait For ore something else if u want
}
LoadingDoneDoData(reader.bytes);
}
void LoadingDoneDoData(bytes data)
{
// your Code here
}
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
add a comment |
just put your while loop inside a CoRoutine and while your request is not done to a yield return. when it is done call a method where you want to use your data:
IEnumerator MyMethod()
{
var reader = new WWW(filePath);
while (!reader.isDone)
{
yield return; // <- use endofFrame or Wait For ore something else if u want
}
LoadingDoneDoData(reader.bytes);
}
void LoadingDoneDoData(bytes data)
{
// your Code here
}
just put your while loop inside a CoRoutine and while your request is not done to a yield return. when it is done call a method where you want to use your data:
IEnumerator MyMethod()
{
var reader = new WWW(filePath);
while (!reader.isDone)
{
yield return; // <- use endofFrame or Wait For ore something else if u want
}
LoadingDoneDoData(reader.bytes);
}
void LoadingDoneDoData(bytes data)
{
// your Code here
}
answered 2 days ago
VampirasuVampirasu
1467
1467
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
add a comment |
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Hey, I know how to make it in a coroutine. The point is I would like to have a simple method that just loads it now. Just like the one above, except mine won't work on a background thread.
– Michał Powłoka
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
Then you use a different thread than the main you have to sync them. Or what do you mean with background thread and load it now?
– Vampirasu
2 days ago
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
I gave up and decided to load it partly in a coroutine. I did some kind of mix of coroutine and async operations. Gona post it in a sec.
– Michał Powłoka
yesterday
add a comment |
I think you can use something like
public static async void ReadAllBytes(string filePath, Action<byte> successCallback)
{
byte result;
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
result = new byte[stream.Length];
await stream.ReadAsync(result, 0, (int)stream.Length);
}
// Now pass the byte to the callback
successCallback.Invoke();
}
(Source)
Than I guess you can use it like
TheClass.ReadAllBytes(
"a/file/path/",
// What shall be done as soon as you have the byte
(bytes) =>
{
// What you want to use the bytes for
}
);
I'm no multi-threading expert but here and also here you can find more examples and how to's for async - await with Unity3d.
Alternatively also the new Unity Jobsystem might be interesting for you.
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
@MichałPowłoka But why can't you use theFileStreamfor that? it returns you the raw bytes just like theWWWwould do ... but with the difference thatFileStreamcan be used async / threaded
– derHugo
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
|
show 5 more comments
I think you can use something like
public static async void ReadAllBytes(string filePath, Action<byte> successCallback)
{
byte result;
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
result = new byte[stream.Length];
await stream.ReadAsync(result, 0, (int)stream.Length);
}
// Now pass the byte to the callback
successCallback.Invoke();
}
(Source)
Than I guess you can use it like
TheClass.ReadAllBytes(
"a/file/path/",
// What shall be done as soon as you have the byte
(bytes) =>
{
// What you want to use the bytes for
}
);
I'm no multi-threading expert but here and also here you can find more examples and how to's for async - await with Unity3d.
Alternatively also the new Unity Jobsystem might be interesting for you.
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
@MichałPowłoka But why can't you use theFileStreamfor that? it returns you the raw bytes just like theWWWwould do ... but with the difference thatFileStreamcan be used async / threaded
– derHugo
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
|
show 5 more comments
I think you can use something like
public static async void ReadAllBytes(string filePath, Action<byte> successCallback)
{
byte result;
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
result = new byte[stream.Length];
await stream.ReadAsync(result, 0, (int)stream.Length);
}
// Now pass the byte to the callback
successCallback.Invoke();
}
(Source)
Than I guess you can use it like
TheClass.ReadAllBytes(
"a/file/path/",
// What shall be done as soon as you have the byte
(bytes) =>
{
// What you want to use the bytes for
}
);
I'm no multi-threading expert but here and also here you can find more examples and how to's for async - await with Unity3d.
Alternatively also the new Unity Jobsystem might be interesting for you.
I think you can use something like
public static async void ReadAllBytes(string filePath, Action<byte> successCallback)
{
byte result;
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
result = new byte[stream.Length];
await stream.ReadAsync(result, 0, (int)stream.Length);
}
// Now pass the byte to the callback
successCallback.Invoke();
}
(Source)
Than I guess you can use it like
TheClass.ReadAllBytes(
"a/file/path/",
// What shall be done as soon as you have the byte
(bytes) =>
{
// What you want to use the bytes for
}
);
I'm no multi-threading expert but here and also here you can find more examples and how to's for async - await with Unity3d.
Alternatively also the new Unity Jobsystem might be interesting for you.
edited 2 days ago
answered 2 days ago
derHugoderHugo
5,11421029
5,11421029
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
@MichałPowłoka But why can't you use theFileStreamfor that? it returns you the raw bytes just like theWWWwould do ... but with the difference thatFileStreamcan be used async / threaded
– derHugo
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
|
show 5 more comments
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
@MichałPowłoka But why can't you use theFileStreamfor that? it returns you the raw bytes just like theWWWwould do ... but with the difference thatFileStreamcan be used async / threaded
– derHugo
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
Hi, I ended up with something similar, but I am afraid your solution won't work. It is not possible to read a file from streaming assets on Android with raw File operations because it is stored in a jar file...
– Michał Powłoka
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
@MichałPowłoka oh I didn't see you want to read it from StreamingAssets. You should be able to read the bytes in anyway ... I don't know what you want to do with it exactly but you will need to unpack etc the content yourself.
– derHugo
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
I know... Unity docs recommend using in such a case WWW class or UnityWebRequest. My problem was I am not allowed to create instance of these on any thread that is not the main thread, other way exception is thrown.
– Michał Powłoka
yesterday
@MichałPowłoka But why can't you use the
FileStream for that? it returns you the raw bytes just like the WWW would do ... but with the difference that FileStream can be used async / threaded– derHugo
yesterday
@MichałPowłoka But why can't you use the
FileStream for that? it returns you the raw bytes just like the WWW would do ... but with the difference that FileStream can be used async / threaded– derHugo
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
Didn't try FileStream tbh. I did try File.ReadAllBytes. I will check it.
– Michał Powłoka
yesterday
|
show 5 more comments
I ended up with the following solution. I did not find a way to load raw file main thread, but I managed to load it in Coroutine and perform further (also heavy) operations on this file on a background Thread. I made a static method like this:
public static void ReadAllBytesInCoroutine(MonoBehaviour context, string filePath, Action<ReadBytesInCoroutineResult> onComplete)
{
context.StartCoroutine(ReadFileBytesAndTakeAction(filePath, onComplete));
}
private static IEnumerator ReadFileBytesAndTakeAction(string filePath, Action<ReadBytesInCoroutineResult> followingAction)
{
WWW reader = null;
try
{
reader = new WWW(filePath);
}
catch(Exception exception)
{
followingAction.Invoke(ReadBytesInCoroutineResult.Failure(exception));
}
while (reader != null && !reader.isDone)
{
yield return null;
}
followingAction.Invoke(ReadBytesInCoroutineResult.Success(reader.bytes));
}
ReadBytesInCoroutineResult is my simple, custom data class:
public class ReadBytesInCoroutineResult
{
public readonly bool successful;
public readonly byte data;
public readonly Exception reason;
private ReadBytesInCoroutineResult(bool successful, byte data, Exception reason)
{
this.successful = successful;
this.data = data;
this.reason = reason;
}
public static ReadBytesInCoroutineResult Success(byte data)
{
return new ReadBytesInCoroutineResult(true, data, null);
}
public static ReadBytesInCoroutineResult Failure(Exception reason)
{
return new ReadBytesInCoroutineResult(true, null, reason);
}
}
This way I have a mechanism to order to load a file in coroutine in any place (as long as it is on the main thread). A file is loaded synchronously, but it is not blocking main thread, because of the coroutine. Later I invoke this function and take acquired bytes on a separate thread, where I perform heavy computing on them.
ResourcesUtils.ReadAllBytesInCoroutine(monoBehavior, filePath, (bytes) => {
//here I run an async method which takes bytes as parameter
});
add a comment |
I ended up with the following solution. I did not find a way to load raw file main thread, but I managed to load it in Coroutine and perform further (also heavy) operations on this file on a background Thread. I made a static method like this:
public static void ReadAllBytesInCoroutine(MonoBehaviour context, string filePath, Action<ReadBytesInCoroutineResult> onComplete)
{
context.StartCoroutine(ReadFileBytesAndTakeAction(filePath, onComplete));
}
private static IEnumerator ReadFileBytesAndTakeAction(string filePath, Action<ReadBytesInCoroutineResult> followingAction)
{
WWW reader = null;
try
{
reader = new WWW(filePath);
}
catch(Exception exception)
{
followingAction.Invoke(ReadBytesInCoroutineResult.Failure(exception));
}
while (reader != null && !reader.isDone)
{
yield return null;
}
followingAction.Invoke(ReadBytesInCoroutineResult.Success(reader.bytes));
}
ReadBytesInCoroutineResult is my simple, custom data class:
public class ReadBytesInCoroutineResult
{
public readonly bool successful;
public readonly byte data;
public readonly Exception reason;
private ReadBytesInCoroutineResult(bool successful, byte data, Exception reason)
{
this.successful = successful;
this.data = data;
this.reason = reason;
}
public static ReadBytesInCoroutineResult Success(byte data)
{
return new ReadBytesInCoroutineResult(true, data, null);
}
public static ReadBytesInCoroutineResult Failure(Exception reason)
{
return new ReadBytesInCoroutineResult(true, null, reason);
}
}
This way I have a mechanism to order to load a file in coroutine in any place (as long as it is on the main thread). A file is loaded synchronously, but it is not blocking main thread, because of the coroutine. Later I invoke this function and take acquired bytes on a separate thread, where I perform heavy computing on them.
ResourcesUtils.ReadAllBytesInCoroutine(monoBehavior, filePath, (bytes) => {
//here I run an async method which takes bytes as parameter
});
add a comment |
I ended up with the following solution. I did not find a way to load raw file main thread, but I managed to load it in Coroutine and perform further (also heavy) operations on this file on a background Thread. I made a static method like this:
public static void ReadAllBytesInCoroutine(MonoBehaviour context, string filePath, Action<ReadBytesInCoroutineResult> onComplete)
{
context.StartCoroutine(ReadFileBytesAndTakeAction(filePath, onComplete));
}
private static IEnumerator ReadFileBytesAndTakeAction(string filePath, Action<ReadBytesInCoroutineResult> followingAction)
{
WWW reader = null;
try
{
reader = new WWW(filePath);
}
catch(Exception exception)
{
followingAction.Invoke(ReadBytesInCoroutineResult.Failure(exception));
}
while (reader != null && !reader.isDone)
{
yield return null;
}
followingAction.Invoke(ReadBytesInCoroutineResult.Success(reader.bytes));
}
ReadBytesInCoroutineResult is my simple, custom data class:
public class ReadBytesInCoroutineResult
{
public readonly bool successful;
public readonly byte data;
public readonly Exception reason;
private ReadBytesInCoroutineResult(bool successful, byte data, Exception reason)
{
this.successful = successful;
this.data = data;
this.reason = reason;
}
public static ReadBytesInCoroutineResult Success(byte data)
{
return new ReadBytesInCoroutineResult(true, data, null);
}
public static ReadBytesInCoroutineResult Failure(Exception reason)
{
return new ReadBytesInCoroutineResult(true, null, reason);
}
}
This way I have a mechanism to order to load a file in coroutine in any place (as long as it is on the main thread). A file is loaded synchronously, but it is not blocking main thread, because of the coroutine. Later I invoke this function and take acquired bytes on a separate thread, where I perform heavy computing on them.
ResourcesUtils.ReadAllBytesInCoroutine(monoBehavior, filePath, (bytes) => {
//here I run an async method which takes bytes as parameter
});
I ended up with the following solution. I did not find a way to load raw file main thread, but I managed to load it in Coroutine and perform further (also heavy) operations on this file on a background Thread. I made a static method like this:
public static void ReadAllBytesInCoroutine(MonoBehaviour context, string filePath, Action<ReadBytesInCoroutineResult> onComplete)
{
context.StartCoroutine(ReadFileBytesAndTakeAction(filePath, onComplete));
}
private static IEnumerator ReadFileBytesAndTakeAction(string filePath, Action<ReadBytesInCoroutineResult> followingAction)
{
WWW reader = null;
try
{
reader = new WWW(filePath);
}
catch(Exception exception)
{
followingAction.Invoke(ReadBytesInCoroutineResult.Failure(exception));
}
while (reader != null && !reader.isDone)
{
yield return null;
}
followingAction.Invoke(ReadBytesInCoroutineResult.Success(reader.bytes));
}
ReadBytesInCoroutineResult is my simple, custom data class:
public class ReadBytesInCoroutineResult
{
public readonly bool successful;
public readonly byte data;
public readonly Exception reason;
private ReadBytesInCoroutineResult(bool successful, byte data, Exception reason)
{
this.successful = successful;
this.data = data;
this.reason = reason;
}
public static ReadBytesInCoroutineResult Success(byte data)
{
return new ReadBytesInCoroutineResult(true, data, null);
}
public static ReadBytesInCoroutineResult Failure(Exception reason)
{
return new ReadBytesInCoroutineResult(true, null, reason);
}
}
This way I have a mechanism to order to load a file in coroutine in any place (as long as it is on the main thread). A file is loaded synchronously, but it is not blocking main thread, because of the coroutine. Later I invoke this function and take acquired bytes on a separate thread, where I perform heavy computing on them.
ResourcesUtils.ReadAllBytesInCoroutine(monoBehavior, filePath, (bytes) => {
//here I run an async method which takes bytes as parameter
});
answered yesterday
Michał PowłokaMichał Powłoka
151113
151113
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54234452%2fandroid-unity-load-a-file-on-background-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown