Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I ".Wait( )" on a ConfiguredTaskAwaitable?

Given the following extension to prevent Tasks from blocking the UI Thread ( probably not the exact correct terminology but whatever ) :

    public static ConfiguredTaskAwaitable DontBlock( this Task T ) {
        return T.ConfigureAwait( false );
    }

    public static ConfiguredTaskAwaitable<T> DontBlock<T>( this Task<T> T2 ) {
        return T2.ConfigureAwait( false );
    }

In some cases ( such as if I need to call an awaitable within an object constructor, or if I need to call .Wait( ) from a WinForms Program.Main( ) method), I need to do the following :

public class Foo{
    public Foo( ){
        //I know full well that the result from DontBlock does not have a 'wait' method, so of course this will fail miserably.
        AwaitableBar.DontBlock( ).Wait( );
    }
}

How can I 'await' it outside an async function/method if I can't call .Wait( ) on it? I see that it has a .GetAwaiter( ) method which returns a ConfiguredTaskAwaiter object, but I have no idea what to do with it, and Google has failed me again... Am I supposed to call GetResult( ) on the returned object right away? Will doing that wait for everything to finish, or just skip right over it, or explode?

like image 374
Will Avatar asked Feb 06 '16 23:02

Will


2 Answers

I agree with the @usr that returning a ConfiguredTaskAwaitable is not ideal. Generally, your asynchronous methods should return tasks. This is a matter of separation of concerns.

Once you have a ConfiguredTaskAwaitable, though, simply call awaitableObj.GetAwaiter().GetResult() (or the appropriate substitution). GetResult() will block.

like image 79
ChiralMichael Avatar answered Nov 03 '22 08:11

ChiralMichael


Probably, you should not return a ConfiguredTaskAwaitable from anything. This is a helper type that is only needed in the await t.ConfigureAwait( false) pattern. await t.DontBlock() is also fine but don't pass this type around. I see no purpose in doing so.

You seem to believe that ConfigureAwait(false) unblocks the UI thread. Not so. Waiting always blocks a thread. Blocking means that this thread cannot continue execution. Wait causes that condition if the underlying task is not completed.

So probably, what you wanted to accomplish doing that is not accomplished. Use await on the UI thread. Use Wait() on non-UI-threads if you want to block.

AwaitableBar.DontBlock( ).Wait() tell me you have some wrong belief. Here, DontBlock does not unblock anything. It does nothing even if this code worked.

If it was that easy to unblock a thread, why would we need await at all?!

like image 44
usr Avatar answered Nov 03 '22 10:11

usr