UniTask icon indicating copy to clipboard operation
UniTask copied to clipboard

How to avoid program getting stuck when forget using utcs.TrySetResult()?

Open zrp2016 opened this issue 1 year ago • 5 comments

See code as following:

public static UniTask GetUTCSUniTask(Action<UniTaskCompletionSource> callback)
{
    var src = GetUTCS();
    if (callback!=null)
    {
        callback?.Invoke(src);
    }
    else
    {
        src.TrySetResult();
    }

    return src.Task;
}

As I set the param callback having await operations in it,then I await the unitask returned by this func,when I forget setting x.TrySetResult(),and this awaiting snippet will be stunning, it's common. So how can I avoid this stunning and get exceptions

zrp2016 avatar Aug 14 '24 02:08 zrp2016

I don't know what you mean by "stunning", but you can overload the function to take an async callback.

public static async UniTask GetUTCSUniTask(Func<UniTaskCompletionSource, UniTask> callback)
{
    var src = GetUTCS();
    if (callback != null)
    {
        await callback.Invoke(src);
    }
    else
    {
        src.TrySetResult();
    }

    await src.Task;
}

timcassell avatar Aug 14 '24 03:08 timcassell

I don't know what you mean by "stunning", but you can overload the function to take an async callback.

public static async UniTask GetUTCSUniTask(Func<UniTaskCompletionSource, UniTask> callback)
{
    var src = GetUTCS();
    if (callback != null)
    {
        await callback.Invoke(src);
    }
    else
    {
        src.TrySetResult();
    }

    await src.Task;
}

"stunning" means program running is stucked,and I don't want GetUTCSUniTask to be an async func,it only returns unitask,as I want to set callback for this func , calling this func and await it.

zrp2016 avatar Aug 14 '24 03:08 zrp2016

There's no way to determine what causes your program to get stuck from that code. You'll have to share more.

timcassell avatar Aug 14 '24 03:08 timcassell

when forget using utcs.TrySetResult()

Oh, the answer is in your title. Obviously if you never set the task it will never continue. Just don't forget to do that. UniTask has a task tracker that you can use to find those types of forever tasks.

timcassell avatar Aug 14 '24 03:08 timcassell

when forget using utcs.TrySetResult()

Oh, the answer is in your title. Obviously if you never set the task it will never continue. Just don't forget to do that. UniTask has a task tracker that you can use to find those types of forever tasks.

yeach, I can track by using it in editor,but I don‘t want the program get stuck,how about the following:

public static UniTask GetUTCSUniTask(Action<UniTaskCompletionSource> callback)
{
    var src = GetUTCS();
    if (callback!=null)
    {
        callback?.Invoke(src);
        // avoid getting stuck
        UniTask.Delay(2).ContinueWith(()=>
        {
            if (!src.Task.Status.IsCompleted())
            {
                src.TrySetException(new TimeoutException("The operation timed out."));
            }
        }).Forget();
    }
    else
    {
        src.TrySetResult();
    }

    return src.Task;
}

I just want to know where I miss setting when not running in editor

zrp2016 avatar Aug 14 '24 03:08 zrp2016

public static UniTask GetUTCSUniTask(Action<UniTaskCompletionSource> callback)
{
    // your code

    var cts = new CancellationTokenSource();
    cts.CancelAfterSlim(1000); // any timespan you prefer
    return src.Task.AttachExternalCancellation(cts.Token);
}

When start an unitask, attach an cancellation token that can auto cancel, timespan can extract to field or paramter

But this maybe not a good practice, you should always handle the status of an unitask

dvsilch avatar Sep 27 '24 16:09 dvsilch