给出以下扩展名以防止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在返回的对象上马上?会这样做等待一切都完成,或者只是跳过它,或者爆炸?
答案 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()
会阻止。