我怎么在ConfiguredTaskAwaitable上“.Wait()”?

时间:2016-02-06 23:58:04

标签: c# asynchronous async-await

给出以下扩展名以防止Tasks阻止UI线程(可能不是完全正确的术语,但无论如何):

    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 );
    }

在某些情况下(例如,如果我需要在对象构造函数中调用awaitable,或者我需要从WinForms .Wait( )方法调用Program.Main( )),我需要执行以下操作:

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( );
    }
}

如果我无法在async上调用.Wait( ),我怎么能在.GetAwaiter( )函数/方法之外'等待'它?我看到它有一个ConfiguredTaskAwaiter方法返回一个GetResult( )对象,但我不知道该如何处理它,谷歌再次失败了......我应该打电话给{{1在返回的对象上马上?会这样做等待一切都完成,或者只是跳过它,或者爆炸?

2 个答案:

答案 0 :(得分:10)

可能你不应该从任何东西返回ConfiguredTaskAwaitable。这是一种只在await t.ConfigureAwait( false)模式中需要的帮助器类型。 await t.DontBlock()也没问题,但不要传递此类型。我认为这样做没有任何意义。

您似乎相信ConfigureAwait(false)取消阻止UI线程。不是这样。等待总是阻塞一个线程。阻止意味着此线程无法继续执行。如果基础任务没有完成,Wait会导致这种情况。

所以可能,你想要完成的事情并没有完成。在UI线程上使用await。如果要阻止,请在非UI线程上使用Wait()

AwaitableBar.DontBlock( ).Wait()告诉我你有一些错误的信念。在这里,DontBlock不会解锁任何内容。即使这段代码有效,它也什么也没做。

如果解锁线程很容易,为什么我们需要await呢?

答案 1 :(得分:5)

我同意@usr认为返回ConfiguredTaskAwaitable并不理想。通常,您的异步方法应该返回任务。这是一个关注点分离的问题。

但是,如果您有ConfiguredTaskAwaitable,只需拨打awaitableObj.GetAwaiter().GetResult()(或相应的替换)即可。 GetResult()会阻止。