0

All I can find online talking about await in async is teaching me how to "wait for a certain period of time", which is not what I want.

I want it to wait until a certain condition is met.

Just lile

yield return new WaitUntil(()=>conditionIsMet);

in Coroutine.

I want to do something like

await Task.WaitUntil(()=>conditionIsMet);

Is such thing possible?

Could somebody please be so kind and help me out?

Thank you very much for your help.

Noob001
  • 93
  • 1
  • 1
  • 7
  • 4
    I'm not sure what you've been reading online, but there's very much **not** what `async` is about – canton7 Sep 22 '21 at 10:06
  • 1
    Have you considered that perhaps the samples you're seeing use `await Task.Delay(someTimePeriod);` as a stand-in for an actual async method (e.g. file i/o, network i/o, etc.)? – ProgrammingLlama Sep 22 '21 at 10:07
  • @canton7 I'm sorry, what I meant is `await` in `async` – Noob001 Sep 22 '21 at 10:11
  • @Llama I'm sorry, I don't quite understand what you mean. – Noob001 Sep 22 '21 at 10:12
  • You said: _"All I can find online talking about await in async is teaching me how to "wait for a certain period of time", which is not what I want."_ - so taking "wait for a certain period of time" leads me to believe that you're seeing `await Task.Delay(somePeriod);`. Is that not what you're saying? If not, what on Earth are you seeing in the examples you refer to? `await` with anything else is presumably waiting for something to complete. – ProgrammingLlama Sep 22 '21 at 10:14
  • @Llama Yes. I'm looking for a way to do something like, `await Task.WaitUntil(()=>conditionIsMet);` Is such thing possible? – Noob001 Sep 22 '21 at 10:16
  • I'm not sure the async/await pattern is what you're looking for, to be honest. – ProgrammingLlama Sep 22 '21 at 10:19
  • 3
    @Noob001 The general idea is that whatever is responsible for making the condition be met will give you a `Task`, and that `Task` will complete when the condition is met. You can then `await` that `Task`, in order to do something when it completes. `await` is not a polling mechanism (although you can build one if you need) – canton7 Sep 22 '21 at 10:21
  • 1
    Who is setting the condition `conditionIsMet`? Is the condition set by another method? Can you add that code? Because you rather not use a while loop to check the condition. – Jeroen van Langen Sep 22 '21 at 10:32
  • I don't have much experience with Unity3d, but normally I would use a [`TaskCompletionSource`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=net-5.0) for this. You should – Jeroen van Langen Sep 22 '21 at 10:35
  • This is probably what you are looking for: https://stackoverflow.com/a/11191070/10413298 – Koray Elbek Sep 22 '21 at 11:18
  • Unity abuses IEnumerable / yield return to implement coroutines, ensuring that they continue execution in sync with game ticks / frames. Do you really want to mix async / await? (http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/ https://stackoverflow.com/questions/64311768/how-to-call-async-function-with-await-within-coroutine-function-in-unity) – Jeremy Lakeman Sep 22 '21 at 14:29
  • @JeremyLakeman I don't think the idea is to mix them at all .. rather wait within a task until a certain condition is met – derHugo Sep 23 '21 at 19:32

3 Answers3

3

you can use UniTask Plugin which Provides an efficient allocation free async/await integration for Unity.

it has a lot of features and it is easy to use.
First download it from here,then include it in your project and use it like this :

using Cysharp.Threading.Tasks;
using UnityEngine;

public class Test : MonoBehaviour
{
    bool _condition;
    // Start is called before the first frame update
    void Start()
    {
        _ = ProcessAsyncTask();
    }

    public async UniTask ProcessAsyncTask()
    {
        await UniTask.WaitUntil( ()=> ConditionResult());
    }

    public bool ConditionResult()
    {
        // _condition 
        return _condition;
    }
}
Qusai Azzam
  • 465
  • 4
  • 19
1

Wouldn't this basically simply be something like

public static class TaskUtils
{
    public static Task WaitUntil(Func<bool> predicate)
    {
        while (!predicate()) { }
    }
}

though for the love of your CPU I would actually rather give your task certain sleep intervals like

public static class TaskUtils
{
    public static async Task WaitUntil(Func<bool> predicate, int sleep = 50)
    {
        while (!predicate())
        {
            await Task.Delay(sleep);
        }
    }
}

and now you could e.g. use something like

public class Example : MonoBehaviour
{
    public bool condition;

    private void Start()
    {
        Task.Run(async ()=> await YourTask());
    }

    public async Task YourTask()
    {
        await TaskUtils.WaitUntil(IsConditionTrue);
        // or as lambda
        //await TaskUtils.WaitUntil(() => condition);

        Debug.Log("Hello!");
    }

    private bool IsConditionTrue()
    {
        return condition;
    }
}

enter image description here

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I think it's probably because the infinite `while` loops. That's almost always NOT a good programming practice. It'll probably better if it was changed to event driven, which will probably better fit their "standard". Just a thought. – Noob001 Oct 01 '21 at 09:10
  • @Noob001 There is no "infinite" loop at all ... as you can see the loop ends as far as the condition is fulfilled .. but it is exactly what OP was asking for: `await` until a condition is fulfilled which is exactly what I provided ^^ – derHugo Oct 01 '21 at 09:32
  • haha yeah it's you ^^ well but that's the case for any while loop of course ... sure it turns infinite if the condition is never met .. but most continous threads are implemented using `while(true)` or at least `while(!stopped)` so this shouldn't be a reason ^^ – derHugo Oct 01 '21 at 13:26
-3

you can create your own ConsitionCheker method, and use it in your MainFunction that gets a boolian which awaits for your condition result

 public async Task<bool> CheckCondition()
        {
            While(true){
               // check the condition
               if(mycondition is true)
                  break;
            }
            return true;
        }



 public void Do(bool consitionResult)
    {
        if(consitionResult){
        // codes
        }
    }

usage :

public  async void Test()
        {
            // waiting for condition met
            // pass the condition result
            Do(await CheckCondition());
        }
  • 1
    What even is this? How does this achieve waiting for a condition to be met? – ProgrammingLlama Sep 22 '21 at 10:23
  • CheckCondition checks the consition, and Do waits for the consition result – pedram rankchian Sep 22 '21 at 10:43
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 22 '21 at 10:44
  • 1
    "I want it to wait until a certain condition is met". Where do you wait until the condition is met? – Jeroen van Langen Sep 22 '21 at 11:25
  • look at usage, Do(await CheckCondition) ,so Do() waits for condition result – pedram rankchian Sep 22 '21 at 11:39
  • 2
    When you `return true` the task is immediately completed, nothing is waiting there. The `CheckCondition` returns a CompletedTask. Try to change this code instead of returning `true/false` directly, return a variable, but only return from the method until you set the variable (by something like a button) to true. That is waiting until the condition is met. – Jeroen van Langen Sep 22 '21 at 11:49