Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by mercem · Aug 01, 2018 at 10:19 AM · synchronization

How can I check if async function is finished?

Hi,

I have read other posts about the same problem but they are not exactly same with my problem. I have created the bool flag to control if the asynchronous function is finished or not. Below snippet is what I am doing right now but the problem is because of while loop Unity freezes as if it never escape while loop but it should break while loop since waitFlag changes in the "getAllElementsAsync" method. Without while loop "getAllElements" method returns the value as null since it returns value before it is changed by "getAllElementsAsync" method. I am open to any other solutions that can solve my problem which is returning value after async method finishes. I have also tried creating coroutine for getAllElementsAsync method but it still returns value before coroutine finishes.

 public class DatabaseConnection : MonoBehaviour {
 
 private DataSnapshot dataSnapshot;
 private bool waitFlag = true;
 
     public Datasnapshot getAllElements(){
     getAllElementsAsync();
 
     while(this.waitFlag){}
     return this.dataSnapshot
     }
 
     public void getAllElementsAsync(){
         FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("someURL");
         DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
        reference.GetValueAsync().ContinueWith(task => {
             if (task.IsFaulted)
             {
                 Debug.Log("not ok");
             }
             else if (task.IsCompleted)
             {
                Debug.Log("ok");
                 this.dataSnapshot = task.Result;
                 this.waitFlag = false;
          }
         });
     }
 }
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Hellium · Aug 01, 2018 at 01:45 PM 0
Share

What didn't you understand during the discussion we had here together? You can't make an asynchronous function to return directly a value in a synchronous function....

4 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by TsvetanTsankov · Aug 01, 2018 at 10:22 AM

Use a Coroutine instead of a void -> https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mercem · Aug 01, 2018 at 10:30 AM 0
Share

Correct me if I am wrong but Startcoroutine is also async function. I also tried that as I said in the question but it didn't help.

avatar image TsvetanTsankov mercem · Aug 01, 2018 at 12:49 PM -1
Share
 public IEnumerator getAllElementsAsync () {
         FirebaseApp.DefaultInstance.SetEditorDatabaseUrl ("someURL");
         DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
         reference.GetValueAsync ().ContinueWith (task => {
             if (task.IsCompleted) {
                 Debug.Log ("Success!");
                 this.dataSnapshot = task.Result;
                 this.waitFlag = false;
             } else (task.IsFaulted) {
                 Debug.Log ("Task is Faulted --> WAITING");
                 yield return null;
             }
         });
     }
avatar image Hellium TsvetanTsankov · Aug 01, 2018 at 01:49 PM 0
Share

This won't work and won't compile. Because getAllElementsAsync returns an IEnumerator but you don't yield anything in it, and the lambda function in the ContinueWith returns void but you try to yield something. The best you can do is:

 public IEnumerator getAllElementsAsync () {
      bool valueReturned = false ;
      FirebaseApp.DefaultInstance.SetEditorDatabaseUrl ("someURL");
      DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
      reference.GetValueAsync ().ContinueWith (task => {
          if (task.IsCompleted) {
              Debug.Log ("Success!");
              this.dataSnapshot = task.Result;
          } else (task.IsFaulted) {
              Debug.Log ("Task is Faulted --> WAITING");
          }
          valueReturned = true ;
      });
      
      while( !valueReturned )
      {
           yield return null ;
      }
  }

But while this works, it does not answer the impossible request of @mercem.

avatar image
1

Answer by TsvetanTsankov · Aug 01, 2018 at 02:07 PM

You provide the function you want to be called back when the data is successfully loaded...

 using System.Collections;
 using System.Collections.Generic;
 using Firebase.Database;
 using UnityEngine;
 public class CallBackCoroutine : MonoBehaviour {
 
     private bool waitFlag = false;
 
     public void GetAll (System.Action<DataSnapshot> callBack) {
         if (waitFlag == false) { // IF it has already started getting the data -> Dont try to retrieve it again
             waitFlag = true;
             StartCoroutine (getAllElementsAsync (callBack));
         }
     }
 
     private IEnumerator getAllElementsAsync (System.Action<DataSnapshot> callBack) {
 
         DataSnapshot dataSnapshot = null;
 
         // FirebaseApp.DefaultInstance.SetEditorDatabaseUrl ("someURL");
         DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
         reference.GetValueAsync ().ContinueWith (task => {
             if (task.IsCompleted)
                 dataSnapshot = task.Result;
             else
                 Debug.Log ("Task is Faulted --> WAITING");
 
         });
 
         yield return new WaitUntil (() => { return dataSnapshot != null; });
 
         waitFlag = false;
         
         callBack (dataSnapshot);
     }
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Hellium · Aug 01, 2018 at 02:32 PM 1
Share

The problem is that mercem does not want to have a callback function, he / she wants the value to be returned synchronously. I tried to explain it was not possible here, but he / she does not seem to understand this is not possible.

By the way, using a coroutine here is not necessary, you just need to call the callback in the lambda expression provided in the ContinueWith function

avatar image TsvetanTsankov Hellium · Aug 01, 2018 at 02:43 PM 0
Share

Yes, you are totally correct and you've provided the example in the other "Question".

Thanks for letting me know about this peculiar case... It's even a different account xD

avatar image mercem Hellium · Aug 01, 2018 at 03:10 PM 0
Share

It is different account because he is my friend we work on same project. Hence we have same problem. None of us was able to solve problem. He tried callback function but as he said in that question you cannot return value inside a lambda function. Now I am trying to achieve solution with this approach but I coudn't find any.

avatar image
-1

Answer by mercem · Aug 01, 2018 at 01:01 PM

I know coroutine is not async but I say startcoroutine is async. I tried to write getAllElements as coroutine then I called it with startcoroutine but it still returns value before coroutine finishes. I need to use this method from outside of this code so it needa to return value. Is there a way to return value from coroutine and assing it to parameter, like “var constant_value = startcoroutine(getallelements());”

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image TsvetanTsankov · Aug 01, 2018 at 01:42 PM 0
Share

How is your coroutine returning a value that you are using?

avatar image hqarts · Aug 01, 2018 at 02:01 PM 0
Share

Can you share me the link to this quote

StartCoroutine is async

avatar image mercem hqarts · Aug 01, 2018 at 03:14 PM 0
Share

Here

avatar image
0

Answer by hqarts · Aug 01, 2018 at 11:00 AM

Coroutine is not async function:


.1. Coroutine is a request to a IEnumerator to get just an element of it at every frame:


.2. Coroutine can start at any frame and can cancel at any frame too.


.3. Coroutine can be finish by itself.


   private IEnumerator SomeCoroutine()
 {
     // (1)
     while (condition)
     {
         // (2)
         print(Time.frameCount);
         yield return null;
     }
     // (3)
 }



(1) : code on this section will invoke just once at the first frame that coroutine called.


(2) : code on this section will executed per frame while condition is true. (you can think this section as code that you write on Update() method)


(3) : code on this section will call once when condition is false. at this state corotine stoped by itself (by ending the loop)


Note: if you stop the coroutine before the condition section (3) will not reach at all.

Note: section (2) called just per frame and you don't break the main threat cause of infinite loop.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

91 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Play(offsetInSamples) acuracy - still cannot get it to work perfectly 5 Answers

Photon Unity Networking (Viking Demo) Error: Argument is out of range. 1 Answer

How do I keep values synchronized over the Photon Network? 1 Answer

Sending texture updates from client to server 1 Answer

Best way to synchronize projectile transform in networked game? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges