在没有等待#2的情况下调用异步方法

时间:2013-11-05 10:12:36

标签: c# asp.net asynchronous async-await c#-5.0

我有一个异步方法:

public async Task<bool> ValidateRequestAsync(string userName, string password)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        string stringResponse = await response.Content.ReadAsStringAsync();

        return bool.Parse(stringResponse);
    }
}

我这样称呼这个方法:

bool isValid = await ValidateRequestAsync("user1", "pass1");

我可以使用同步方法调用相同的方法,而不使用await关键字吗?

例如:

public bool ValidateRequest(string userName, string password)
{
    return ValidateRequestAsync(userName, password).Result;
}

我认为这会导致僵局。

修改

调用上面的方法会使调用永远不会结束。 (该方法不再到达终点)

3 个答案:

答案 0 :(得分:61)

如果从单线程执行上下文(如UI线程)调用异步方法,并等待同步结果,则死锁的可能性很高。在您的示例中,该概率为100%

想一想。致电

后会发生什么
ValidateRequestAsync(userName, password).Result

您调用方法ValidateRequestAsync。在那里你调用ReadAsStringAsync。结果是,任务将返回到UI线程,并且计划继续在UI线程可用时继续执行。但是,当然,它永远不可用,因为它正在等待(阻止)任务完成。但是任务无法完成,因为它正在等待UI线程变得可用。死锁。

有一些方法可以防止这种僵局,但它们都是一个坏主意。为了完整起见,以下内容可能有效:

Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

这是一个坏主意,因为你仍然阻止你的UI线程等待并且没有任何用处。

那么解决方案是什么呢?一路走异步。 UI线程上的原始调用者可能是一些事件处理程序,因此请确保它是异步的。

答案 1 :(得分:5)

您可以使用return ValidateRequestAsync(userName,password).GetAwaiter()。GetResult();

答案 2 :(得分:0)

对我来说,它在异步调用中使用.ConfigureAwait(false)设置起作用。我有类似

return await Entities.SingleOrDefaultAsync(.....).ConfigureAwait(false);