简体   繁体   中英

Async/await style for UI in Unity

I want to implement async / await style in Unity for UI. It occurs to me that you can write a static class in which to define a method like this public static async Task<Button> WaitForButtonClickAsync(CancellationToken ct, params Button[] buttons) This method will wait for any of the transferred buttons to be pressed with Task.whenAny , and then it will return a button. But what's after that? I can only come up with something like a giant switch-case block to figure out which button was pressed or pass the buttons with a callback to the method right away, but it seems to me that these are not the best solutions.

I've used this pattern very successfully. But you are right about the giant switch-case, it does require a bit of boilerplate. But then again, it's not actually any shorter with callbacks.

Example:

Button pressedButton = await WaitForButtonClickAsync(ct, button1, button2, button3);
if (pressedButton == button1) await DoStuff1(ct);    
if (pressedButton == button2) await DoStuff2(ct);
if (pressedButton == button3) await DoStuff3(ct);

Or with callbacks (Note that we aren't removing event handlers here, so this solution isn't at all shorter in reality), though here we don't get the advantage of chaining async code:

button1.onClick += () => DoStuff1();
button2.onClick += () => DoStuff2();
button3.onClick += () => DoStuff3();

You could also make some kind of helper to avoid the if-elses, something like this:

await WaitForButtonHandlersAsync(ct, 
                                (button1, DoStuff1), 
                                (button2, DoStuff2),
                                (button3, DoStuff3));

But as you start mixing in other awaits in addition to buttons, this can get messy, and I've always just fallen back to if-else listings.

EDIT: One thing to ad is that you can also group things. For example if you have a commonly used set of navigation buttons/gestures in addition to a few context specific buttons, you can bundle the navigation buttons into one task. This example also contains the usage of linked tokens presented in the video.

using (var cts = CreateLinkedTokenSource(ct))
{
    var navigationTask = WaitForNavigationEventAsync(cts.Token);
    var buttonTask1 = WaitForButtonClickAsync(cts.Token, button1);
    var buttonTask2 = WaitForButtonClickAsync(cts.Token, button2);

    var finishedTask = await Task.WhenAny(navigationTask, buttonTask1, buttonTask2);
    await finishedTask; // "Reveal" and propagate exceptions
    cts.Cancel();

    if (finishedTask == navigationTask) await Navigate(navigationTask.Result, ct);
    if (finishedTask == buttonTask1) await DoStuff1(ct);
    if (finishedTask == buttonTask2) await DoStuff2(ct);
}

With this kind of constructs, the listing never gets out of hands and you avoid some repeating code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM