46

我有一个异步方法:

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

我认为这会导致僵局。

编辑

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

4

3 回答 3

70

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

想想看。当你打电话时会发生什么

ValidateRequestAsync(userName, password).Result

您调用方法 ValidateRequestAsync。在那里你调用 ReadAsStringAsync。结果是任务将返回给 UI 线程,并计划在 UI 线程可用时继续在其上执行的延续。但当然,它永远不会变得可用,因为它正在等待(阻塞)任务完成。但任务无法完成,因为它正在等待 UI 线程变得可用。僵局。

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

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

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

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

于 2013-11-05T11:16:18.397 回答
8

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

于 2018-07-18T15:27:33.837 回答
0

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

return await Entities.SingleOrDefaultAsync(.....).ConfigureAwait(false);
于 2019-12-10T11:39:16.237 回答