Android Unity - Load a file on background thread












1















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?










share|improve this question



























    1















    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?










    share|improve this question

























      1












      1








      1








      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?










      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 2 days ago









      Michał PowłokaMichał Powłoka

      151113




      151113
























          3 Answers
          3






          active

          oldest

          votes


















          1














          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
          }





          share|improve this answer
























          • 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



















          1














          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.






          share|improve this answer


























          • 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 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



















          0














          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

          });





          share|improve this answer























            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            1














            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
            }





            share|improve this answer
























            • 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
















            1














            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
            }





            share|improve this answer
























            • 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














            1












            1








            1







            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
            }





            share|improve this answer













            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
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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



















            • 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













            1














            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.






            share|improve this answer


























            • 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 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
















            1














            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.






            share|improve this answer


























            • 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 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














            1












            1








            1







            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.






            share|improve this answer















            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 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



















            • 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 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

















            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











            0














            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

            });





            share|improve this answer




























              0














              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

              });





              share|improve this answer


























                0












                0








                0







                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

                });





                share|improve this answer













                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

                });






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered yesterday









                Michał PowłokaMichał Powłoka

                151113




                151113






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Callistus III

                    Plistias Cous

                    Index Sanctorum