【发布时间】:2011-02-17 18:07:48
【问题描述】:
代码如下:
static class AsyncFinally
{
static async Task<int> Func( int n )
{
try
{
Console.WriteLine( " Func: Begin #{0}", n );
await TaskEx.Delay( 100 );
Console.WriteLine( " Func: End #{0}", n );
return 0;
}
finally
{
Console.WriteLine( " Func: Finally #{0}", n );
}
}
static async Task Consumer()
{
for ( int i = 1; i <= 2; i++ )
{
Console.WriteLine( "Consumer: before await #{0}", i );
int u = await Func( i );
Console.WriteLine( "Consumer: after await #{0}", i );
}
Console.WriteLine( "Consumer: after the loop" );
}
public static void AsyncTest()
{
Task t = TaskEx.RunEx( Consumer );
t.Wait();
Console.WriteLine( "After the wait" );
}
}
这是输出:
Consumer: before await #1
Func: Begin #1
Func: End #1
Consumer: after await #1
Consumer: before await #2
Func: Begin #2
Func: Finally #1
Func: End #2
Consumer: after await #2
Consumer: after the loop
Func: Finally #2
After the wait
如您所见,finally 块的执行时间比您预期的要晚很多。
有什么解决方法吗?
提前致谢!
【问题讨论】:
-
看看反射器生成的 C# 会很有趣,看看编译器生成的状态机是什么样子的。这就是答案所在。
-
@btlog:我做到了。它将我的“return 0”转换为某个“SetResult()”调用,该调用在同一个线程上从内部调用“Consumer”的等待块。有趣的是异常,“finally”块在它应该执行的时候执行,即在控件离开“Func”之前。
-
这是一个很棒的发现 - 组成我的答案:)