奇怪的等待行为

时间:2017-07-25 14:46:31

标签: c# async-await task-parallel-library

我有一个像这样的异步方法

public async Task<bool> FooAsync() 
{ 
    return await SomeThirdPartyLib.SomeMethodReturningBoolAsync().ConfigureAwait(false);
}

然后我有一个代码在循环中调用它:

for (var i = 0; i < 10; i++)
{
    ok &= await FooAsync().ConfigureAwait(false);
}

在我的情况下,这将在2或3或其他数量的周期后挂起我的过程。但是当我将代码更改为

for (var i = 0; i < 10; i++)
{
    ok &= await FooAsync()
        .ContinueWith(t => {
            if (t.IsCompleted)
            {
                return t.Result;
            }
            return false;
        })
        .ConfigureAwait(false);
}

完全相同的代码有效。有什么想法吗?

编辑:我刚刚更改了示例代码以显示FooAsync原则上的内容。回复一些已经给出的答案和评论:我不确切知道SomeMethodReturningBoolAsync的确切含义。我的ContinueWith实际上没有任何用处,这一事实让我感到震惊。

2 个答案:

答案 0 :(得分:6)

你的FooAsync()尽管有名字,实际上是在同步进行工作,所以既然你在UI线程上开始工作,它将继续在UI线程上完成所有工作。 / p>

当您添加ContinueWith时,您强制在线程池线程上运行一个方法(无效),因此只有第一个FooAsync调用实际上正在运行UI线程。由于ConfigureAwait(false),所有后续调用都将位于线程池线程上。

正确的修复是实际调整FooAsync,以便它实际上异步地工作,而不是同步,或者如果它没有做任何概念上的异步工作,那么它应该是同步方法,不返回Task,并且在此方法中使用Task.Run调用,因为它需要在另一个线程中执行同步工作。 / p>

答案 1 :(得分:0)

答案在你的问题里面,发生了什么事情解释你Servy jet - 刚开始在线程池中:

for (var i = 0; i < 10; i++)
{
 ok &= await Task.Run(() => { return FooAsync(); }).ConfigureAwait(false);
}